pub struct PyCapsule(/* private fields */);Expand description
Represents a Python Capsule as described in Capsules:
This subtype of PyObject represents an opaque value, useful for C extension modules who need to pass an opaque value (as a void* pointer) through Python code to other C code. It is often used to make a C function pointer defined in one module available to other modules, so the regular import mechanism can be used to access C APIs defined in dynamically loaded modules.
Values of this type are accessed via PyO3’s smart pointers, e.g. as
Py<PyCapsule> or Bound<'py, PyCapsule>.
For APIs available on capsule objects, see the PyCapsuleMethods trait which is implemented for
Bound<'py, PyCapsule>.
§Example
use pyo3::{prelude::*, types::PyCapsule, ffi::c_str};
#[repr(C)]
struct Foo {
pub val: u32,
}
let r = Python::attach(|py| -> PyResult<()> {
let foo = Foo { val: 123 };
let capsule = PyCapsule::new(py, foo, Some(c"builtins.capsule".to_owned()))?;
let module = PyModule::import(py, "builtins")?;
module.add("capsule", capsule)?;
let cap: &Foo = unsafe { PyCapsule::import(py, c"builtins.capsule")? };
assert_eq!(cap.val, 123);
Ok(())
});
assert!(r.is_ok());Implementations§
Source§impl PyCapsule
impl PyCapsule
Sourcepub fn new<T: 'static + Send + AssertNotZeroSized>(
py: Python<'_>,
value: T,
name: Option<CString>,
) -> PyResult<Bound<'_, Self>>
pub fn new<T: 'static + Send + AssertNotZeroSized>( py: Python<'_>, value: T, name: Option<CString>, ) -> PyResult<Bound<'_, Self>>
Constructs a new capsule whose contents are value, associated with name.
name is the identifier for the capsule; if it is stored as an attribute of a module,
the name should be in the format "modulename.attribute".
It is checked at compile time that the type T is not zero-sized. Rust function items
need to be cast to a function pointer (fn(args) -> result) to be put into a capsule.
§Example
use pyo3::{prelude::*, types::PyCapsule, ffi::c_str};
use std::ffi::CStr;
use std::ptr::NonNull;
// this can be c"foo" on Rust 1.77+
const NAME: &CStr = c"foo";
Python::attach(|py| {
let capsule = PyCapsule::new(py, 123_u32, Some(NAME.to_owned())).unwrap();
let val: NonNull<u32> = capsule.pointer_checked(Some(NAME)).unwrap().cast();
assert_eq!(unsafe { *val.as_ref() }, 123);
});However, attempting to construct a PyCapsule with a zero-sized type will not compile:
use pyo3::{prelude::*, types::PyCapsule};
Python::attach(|py| {
let capsule = PyCapsule::new(py, (), None).unwrap(); // Oops! `()` is zero sized!
});Sourcepub fn new_with_destructor<T: 'static + Send + AssertNotZeroSized, F: FnOnce(T, *mut c_void) + Send>(
py: Python<'_>,
value: T,
name: Option<CString>,
destructor: F,
) -> PyResult<Bound<'_, Self>>
pub fn new_with_destructor<T: 'static + Send + AssertNotZeroSized, F: FnOnce(T, *mut c_void) + Send>( py: Python<'_>, value: T, name: Option<CString>, destructor: F, ) -> PyResult<Bound<'_, Self>>
Constructs a new capsule whose contents are value, associated with name.
Also provides a destructor: when the PyCapsule is destroyed, it will be passed the original object,
as well as a *mut c_void which will point to the capsule’s context, if any.
The destructor must be Send, because there is no guarantee which thread it will eventually
be called from.
Sourcepub unsafe fn new_with_pointer<'py>(
py: Python<'py>,
pointer: NonNull<c_void>,
name: &'static CStr,
) -> PyResult<Bound<'py, Self>>
pub unsafe fn new_with_pointer<'py>( py: Python<'py>, pointer: NonNull<c_void>, name: &'static CStr, ) -> PyResult<Bound<'py, Self>>
Constructs a new capsule from a raw pointer.
Unlike PyCapsule::new, which stores a value and sets the capsule’s pointer
to that value’s address, this method uses the pointer directly. This is useful
for APIs that expect the capsule to hold a specific address (e.g., a function
pointer for FFI) rather than a pointer to owned data.
The capsule’s name should follow Python’s naming convention:
"module.attribute" for capsules stored as module attributes.
§Safety
- The pointer must be valid for its intended use case.
- If the pointer refers to data, that data must outlive the capsule.
- No destructor is registered; use
PyCapsule::new_with_pointer_and_destructorif cleanup is needed.
§Example
use pyo3::{prelude::*, types::PyCapsule};
use std::ffi::c_void;
use std::ptr::NonNull;
extern "C" fn my_ffi_handler(_: *mut c_void) -> *mut c_void {
std::ptr::null_mut()
}
Python::attach(|py| {
let ptr = NonNull::new(my_ffi_handler as *mut c_void).unwrap();
// SAFETY: `ptr` is a valid function pointer
let capsule = unsafe {
PyCapsule::new_with_pointer(py, ptr, c"my_module.my_ffi_handler")
}.unwrap();
let retrieved = capsule.pointer_checked(Some(c"my_module.my_ffi_handler")).unwrap();
assert_eq!(retrieved.as_ptr(), my_ffi_handler as *mut c_void);
});Sourcepub unsafe fn new_with_pointer_and_destructor<'py>(
py: Python<'py>,
pointer: NonNull<c_void>,
name: &'static CStr,
destructor: Option<PyCapsule_Destructor>,
) -> PyResult<Bound<'py, Self>>
pub unsafe fn new_with_pointer_and_destructor<'py>( py: Python<'py>, pointer: NonNull<c_void>, name: &'static CStr, destructor: Option<PyCapsule_Destructor>, ) -> PyResult<Bound<'py, Self>>
Constructs a new capsule from a raw pointer with an optional destructor.
This is the full-featured version of PyCapsule::new_with_pointer, allowing
a destructor to be called when the capsule is garbage collected.
Unlike PyCapsule::new_with_destructor, the destructor here must be a raw
extern "C" function pointer, not a Rust closure. This is because there is
no internal storage for a closure—the capsule holds only the raw pointer you
provide.
§Safety
- The pointer must be valid for its intended use case.
- If the pointer refers to data, that data must remain valid for the capsule’s lifetime, or the destructor must clean it up.
- The destructor, if provided, must be safe to call from any thread.
- The destructor should not panic. Panics cannot unwind across the FFI boundary into Python, so a panic will abort the process.
§Example
use pyo3::{prelude::*, types::PyCapsule};
use std::ffi::c_void;
use std::ptr::NonNull;
unsafe extern "C" fn free_data(capsule: *mut pyo3::ffi::PyObject) {
let ptr = pyo3::ffi::PyCapsule_GetPointer(capsule, c"my_module.data".as_ptr());
if !ptr.is_null() {
drop(Box::from_raw(ptr as *mut u32));
}
}
Python::attach(|py| {
let data = Box::new(42u32);
let ptr = NonNull::new(Box::into_raw(data).cast::<c_void>()).unwrap();
// SAFETY: `ptr` is valid; `free_data` will deallocate it
let capsule = unsafe {
PyCapsule::new_with_pointer_and_destructor(
py,
ptr,
c"my_module.data",
Some(free_data),
)
}.unwrap();
});Sourcepub unsafe fn import<'py, T>(py: Python<'py>, name: &CStr) -> PyResult<&'py T>
pub unsafe fn import<'py, T>(py: Python<'py>, name: &CStr) -> PyResult<&'py T>
Imports an existing capsule.
The name should match the path to the module attribute exactly in the form
of "module.attribute", which should be the same as the name within the capsule.
§Safety
It must be known that the capsule imported by name contains an item of type T.
Trait Implementations§
Source§impl PyTypeInfo for PyCapsule
impl PyTypeInfo for PyCapsule
Source§const NAME: &'static str = "PyCapsule"
const NAME: &'static str = "PyCapsule"
::type_object(py).name() to get the correct runtime valueSource§const MODULE: Option<&'static str>
const MODULE: Option<&'static str>
::type_object(py).module() to get the correct runtime valueSource§const TYPE_HINT: PyStaticExpr
const TYPE_HINT: PyStaticExpr
Source§fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject
fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject
Source§fn is_type_of(obj: &Bound<'_, PyAny>) -> bool
fn is_type_of(obj: &Bound<'_, PyAny>) -> bool
object is an instance of this type or a subclass of this type.impl DerefToPyAny for PyCapsule
Auto Trait Implementations§
impl !Freeze for PyCapsule
impl !RefUnwindSafe for PyCapsule
impl !Send for PyCapsule
impl !Sync for PyCapsule
impl Unpin for PyCapsule
impl UnwindSafe for PyCapsule
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more