PyCapsuleMethods

Trait PyCapsuleMethods 

Source
pub trait PyCapsuleMethods<'py>: Sealed {
    // Required methods
    fn set_context(&self, context: *mut c_void) -> PyResult<()>;
    fn context(&self) -> PyResult<*mut c_void>;
    unsafe fn reference<T>(&self) -> &T;
    fn pointer(&self) -> *mut c_void;
    fn pointer_checked(&self, name: Option<&CStr>) -> PyResult<NonNull<c_void>>;
    fn is_valid(&self) -> bool;
    fn is_valid_checked(&self, name: Option<&CStr>) -> bool;
    fn name(&self) -> PyResult<Option<CapsuleName>>;
}
Expand description

Implementation of functionality for PyCapsule.

These methods are defined for the Bound<'py, PyCapsule> smart pointer, so to use method call syntax these methods are separated into a trait, because stable Rust does not yet support arbitrary_self_types.

§Name checking

Capsules contain pointers to arbitrary data which is cast to a specific type at runtime. This is inherently quite dangerous, so Python allows capsules to be “named” to provide a hint as to what data is contained in the capsule. Although not a perfect solution, this is better than nothing.

The methods in this trait take the name as an Option<&CStr>, which is compared to the name stored in the capsule (with None being used to indicate the capsule has no name).

Required Methods§

Source

fn set_context(&self, context: *mut c_void) -> PyResult<()>

Sets the context pointer in the capsule.

Returns an error if this capsule is not valid.

§Notes

The context is treated much like the value of the capsule, but should likely act as a place to store any state management when using the capsule.

If you want to store a Rust value as the context, and drop it from the destructor, use Box::into_raw to convert it into a pointer, see the example.

§Example
use std::ffi::c_void;
use std::sync::mpsc::{channel, Sender};
use pyo3::{prelude::*, types::PyCapsule};

let (tx, rx) = channel::<String>();

fn destructor(val: u32, context: *mut c_void) {
    let ctx = unsafe { *Box::from_raw(context.cast::<Sender<String>>()) };
    ctx.send("Destructor called!".to_string()).unwrap();
}

Python::attach(|py| {
    let capsule =
        PyCapsule::new_with_destructor(py, 123, None, destructor as fn(u32, *mut c_void))
            .unwrap();
    let context = Box::new(tx);  // `Sender<String>` is our context, box it up and ship it!
    capsule.set_context(Box::into_raw(context).cast()).unwrap();
    // This scope will end, causing our destructor to be called...
});

assert_eq!(rx.recv(), Ok("Destructor called!".to_string()));
Source

fn context(&self) -> PyResult<*mut c_void>

Gets the current context stored in the capsule. If there is no context, the pointer will be null.

Returns an error if this capsule is not valid.

Source

unsafe fn reference<T>(&self) -> &T

👎Deprecated since 0.27.0: to be removed, see pointer_checked()

Obtains a reference dereferenced from the pointer of this capsule, without checking its name.

Because this method encourages dereferencing the pointer for longer than necessary, it is deprecated. Prefer to use pointer_checked() and dereference the pointer only for as short a time as possible.

§Safety

This performs a dereference of the pointer returned from pointer().

See the safety notes on pointer_checked().

Source

fn pointer(&self) -> *mut c_void

👎Deprecated since 0.27.0: use pointer_checked() instead

Gets the raw pointer stored in this capsule, without checking its name.

Source

fn pointer_checked(&self, name: Option<&CStr>) -> PyResult<NonNull<c_void>>

Gets the raw pointer stored in this capsule.

Returns an error if the capsule is not valid with the given name.

§Safety

This function itself is not unsafe, but dereferencing the returned pointer to produce a reference is very dangerous:

  • The pointer will need to be .cast() to a concrete type before dereferencing. As per name checking, there is no way to statically guarantee this cast is correct, the name is the best available hint to guard against accidental misuse.
  • Arbitrary Python code can change the contents of the capsule, which may invalidate the pointer. The pointer and the reference produced by dereferencing the pointer should both be considered invalid after arbitrary Python code has run.

Users should take care to cast to the correct type and consume the pointer for as little duration as possible.

Source

fn is_valid(&self) -> bool

👎Deprecated since 0.27.0: use is_valid_checked() instead

Checks if the capsule pointer is not null.

This does not perform any check on the name of the capsule, which is the only mechanism that Python provides to make sure that the pointer has the expected type. Prefer to use is_valid_checked() instead.

Source

fn is_valid_checked(&self, name: Option<&CStr>) -> bool

Checks that the capsule name matches name and that the pointer is not null.

Source

fn name(&self) -> PyResult<Option<CapsuleName>>

Retrieves the name of this capsule, if set.

Returns an error if this capsule is not valid.

See CapsuleName for details of how to consume the return value.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

Source§

impl<'py> PyCapsuleMethods<'py> for Bound<'py, PyCapsule>