PyCapsule

Struct PyCapsule 

Source
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

Source

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!
});
Source

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.

Source

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_destructor if 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);
});
Source

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();
});
Source

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

Source§

const NAME: &'static str = "PyCapsule"

👎Deprecated since 0.28.0: prefer using ::type_object(py).name() to get the correct runtime value
Class name.
Source§

const MODULE: Option<&'static str>

👎Deprecated since 0.28.0: prefer using ::type_object(py).module() to get the correct runtime value
Module name, if any.
Source§

const TYPE_HINT: PyStaticExpr

Provides the full python type as a type hint.
Source§

fn type_object_raw(py: Python<'_>) -> *mut PyTypeObject

Returns the PyTypeObject instance for this type.
Source§

fn is_type_of(obj: &Bound<'_, PyAny>) -> bool

Checks if object is an instance of this type or a subclass of this type.
Source§

fn type_object(py: Python<'_>) -> Bound<'_, PyType>

Returns the safe abstraction over the type object.
Source§

fn is_exact_type_of(object: &Bound<'_, PyAny>) -> bool

Checks if object is an instance of this type.
Source§

impl DerefToPyAny for PyCapsule

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> PyTypeCheck for T
where T: PyTypeInfo,

Source§

const NAME: &'static str = const NAME: &'static str = T::NAME;

👎Deprecated since 0.27.0: Use ::classinfo_object() instead and format the type name at runtime. Note that using built-in cast features is often better than manual PyTypeCheck usage.
Name of self. This is used in error messages, for example.
Source§

const TYPE_HINT: PyStaticExpr = const TYPE_HINT: PyStaticExpr = <T as PyTypeInfo>::TYPE_HINT;

Provides the full python type of the allowed values as a Python type hint.
Source§

fn type_check(object: &Bound<'_, PyAny>) -> bool

Checks if object is an instance of Self, which may include a subtype. Read more
Source§

fn classinfo_object(py: Python<'_>) -> Bound<'_, PyAny>

Returns the expected type as a possible argument for the isinstance and issubclass function. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.