rustpython_vm/builtins/
capsule.rs1use super::PyType;
2use crate::{
3 AsObject, Context, Py, PyObject, PyPayload, PyResult, VirtualMachine,
4 class::PyClassImpl,
5 types::{Destructor, Representable},
6};
7use core::ffi::{CStr, c_void};
8use core::sync::atomic::AtomicPtr;
9
10#[pyclass(module = false, name = "PyCapsule")]
12#[derive(Debug)]
13pub struct PyCapsule {
14 ptr: AtomicPtr<c_void>,
15 context: AtomicPtr<c_void>,
16 name: Option<&'static CStr>,
17 destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
18}
19
20impl PyPayload for PyCapsule {
21 #[inline]
22 fn class(ctx: &Context) -> &'static Py<PyType> {
23 ctx.types.capsule_type
24 }
25}
26
27#[pyclass(with(Representable, Destructor), flags(DISALLOW_INSTANTIATION))]
28impl PyCapsule {
29 pub fn new(
30 ptr: *mut c_void,
31 name: Option<&'static CStr>,
32 destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
33 ) -> Self {
34 Self {
35 ptr: ptr.into(),
36 context: core::ptr::null_mut::<c_void>().into(),
37 name,
38 destructor,
39 }
40 }
41
42 pub fn pointer(&self) -> *mut c_void {
43 self.ptr.load(core::sync::atomic::Ordering::Relaxed)
44 }
45
46 pub fn set_pointer(&self, pointer: *mut c_void) {
47 self.ptr
48 .store(pointer, core::sync::atomic::Ordering::Relaxed);
49 }
50
51 pub fn context(&self) -> *mut c_void {
52 self.context.load(core::sync::atomic::Ordering::Relaxed)
53 }
54
55 pub fn set_context(&self, context: *mut c_void) {
56 self.context
57 .store(context, core::sync::atomic::Ordering::Relaxed);
58 }
59
60 pub fn name(&self) -> Option<&CStr> {
61 self.name
62 }
63
64 fn destructor(&self) -> Option<unsafe extern "C" fn(_: *mut PyObject)> {
65 self.destructor
66 }
67}
68
69impl Representable for PyCapsule {
70 #[inline]
71 fn repr_str(_zelf: &Py<Self>, _vm: &crate::VirtualMachine) -> PyResult<String> {
72 Ok("<capsule object>".to_string())
73 }
74}
75
76impl Destructor for PyCapsule {
77 fn del(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
78 if zelf.pointer().is_null() {
79 return Ok(());
80 }
81 if let Some(destructor) = zelf.destructor() {
82 unsafe { destructor(zelf.as_object().as_raw().cast_mut()) };
83 }
84 Ok(())
85 }
86}
87
88pub(crate) fn init(context: &'static Context) {
89 PyCapsule::extend_class(context, context.types.capsule_type);
90}