Allow creating PyCapsule objects (#7595)

This commit is contained in:
Bas Schoenmaeckers authored and GitHub committed 2026-04-14 09:44:02 +09:00
1 parent 76755524df
commit 4875323705
2 files changed
+51 -11

No files matched your search

+39 -7
View File
@@ -1,14 +1,19 @@
use super::PyType;
use crate::{Context, Py, PyPayload, PyResult, class::PyClassImpl, types::Representable};
use crate::{
AsObject, Context, Py, PyObject, PyPayload, PyResult, VirtualMachine,
class::PyClassImpl,
types::{Destructor, Representable},
};
use core::ffi::c_void;
use core::sync::atomic::AtomicPtr;
/// PyCapsule - a container for C pointers.
/// In RustPython, this is a minimal implementation for compatibility.
#[pyclass(module = false, name = "PyCapsule")]
#[derive(Debug, Clone, Copy)]
#[derive(Debug)]
pub struct PyCapsule {
// Capsules store opaque pointers; we don't expose the actual pointer functionality
// since RustPython doesn't have the same C extension model as CPython.
_private: (),
ptr: AtomicPtr<c_void>,
destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
}
impl PyPayload for PyCapsule {
@@ -18,8 +23,26 @@ impl PyPayload for PyCapsule {
}
}
#[pyclass(with(Representable), flags(DISALLOW_INSTANTIATION))]
impl PyCapsule {}
#[pyclass(with(Representable, Destructor), flags(DISALLOW_INSTANTIATION))]
impl PyCapsule {
pub fn new(
ptr: *mut c_void,
destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
) -> Self {
Self {
ptr: ptr.into(),
destructor,
}
}
pub fn pointer(&self) -> *mut c_void {
self.ptr.load(core::sync::atomic::Ordering::Relaxed)
}
fn destructor(&self) -> Option<unsafe extern "C" fn(_: *mut PyObject)> {
self.destructor
}
}
impl Representable for PyCapsule {
#[inline]
@@ -28,6 +51,15 @@ impl Representable for PyCapsule {
}
}
impl Destructor for PyCapsule {
fn del(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<()> {
if let Some(destructor) = zelf.destructor() {
unsafe { destructor(zelf.as_object().as_raw().cast_mut()) };
}
Ok(())
}
}
pub fn init(context: &'static Context) {
PyCapsule::extend_class(context, context.types.capsule_type);
}
+12 -4
View File
@@ -1,9 +1,9 @@
use crate::{
PyResult, VirtualMachine,
PyObject, PyResult, VirtualMachine,
builtins::{
PyByteArray, PyBytes, PyComplex, PyDict, PyDictRef, PyEllipsis, PyFloat, PyFrozenSet,
PyInt, PyIntRef, PyList, PyListRef, PyNone, PyNotImplemented, PyStr, PyStrInterned,
PyTuple, PyTupleRef, PyType, PyTypeRef, PyUtf8Str,
PyByteArray, PyBytes, PyCapsule, PyComplex, PyDict, PyDictRef, PyEllipsis, PyFloat,
PyFrozenSet, PyInt, PyIntRef, PyList, PyListRef, PyNone, PyNotImplemented, PyStr,
PyStrInterned, PyTuple, PyTupleRef, PyType, PyTypeRef, PyUtf8Str,
bool_::PyBool,
code::{self, PyCode},
descriptor::{
@@ -752,6 +752,14 @@ impl Context {
let code = code.into_code_object(self);
PyRef::new_ref(PyCode::new(code), self.types.code_type.to_owned(), None)
}
pub fn new_capsule(
&self,
ptr: *mut core::ffi::c_void,
destructor: Option<unsafe extern "C" fn(_: *mut PyObject)>,
) -> PyRef<PyCapsule> {
PyCapsule::new(ptr, destructor).into_ref(self)
}
}
impl AsRef<Self> for Context {