Expand conversions documentation
This commit is contained in:
parent
dce4377eb4
commit
f34b92a368
|
@ -10,30 +10,88 @@ use crate::{
|
||||||
};
|
};
|
||||||
use std::ptr::NonNull;
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
/// This trait represents that **we can do zero-cost conversion from the object
|
/// Returns a borrowed pointer to a Python object.
|
||||||
/// to a FFI pointer**.
|
|
||||||
///
|
///
|
||||||
/// This trait is implemented for types that internally wrap a pointer to a Python object.
|
/// The returned pointer will be valid for as long as `self` is. It may be null depending on the
|
||||||
|
/// implementation.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```rust
|
||||||
/// use pyo3::{prelude::*, AsPyPointer};
|
/// use pyo3::prelude::*;
|
||||||
|
/// use pyo3::AsPyPointer;
|
||||||
|
/// use pyo3::types::PyString;
|
||||||
|
/// use pyo3::ffi;
|
||||||
|
///
|
||||||
/// Python::with_gil(|py| {
|
/// Python::with_gil(|py| {
|
||||||
/// let dict = pyo3::types::PyDict::new(py);
|
/// let s: Py<PyString> = "foo".into_py(py);
|
||||||
/// // All native object wrappers implement AsPyPointer!!!
|
/// let ptr = s.as_ptr();
|
||||||
/// assert_ne!(dict.as_ptr(), std::ptr::null_mut());
|
///
|
||||||
|
/// let is_really_a_pystring = unsafe { ffi::PyUnicode_CheckExact(ptr) };
|
||||||
|
/// assert_eq!(is_really_a_pystring, 1);
|
||||||
/// });
|
/// });
|
||||||
/// ```
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// It is your responsibility to make sure that the underlying Python object is not dropped too
|
||||||
|
/// early. For example, the following code will cause undefined behavior:
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// # use pyo3::prelude::*;
|
||||||
|
/// # use pyo3::AsPyPointer;
|
||||||
|
/// # use pyo3::ffi;
|
||||||
|
/// #
|
||||||
|
/// Python::with_gil(|py| {
|
||||||
|
/// let ptr: *mut ffi::PyObject = 0xabad1dea_u32.into_py(py).as_ptr();
|
||||||
|
///
|
||||||
|
/// let isnt_a_pystring = unsafe {
|
||||||
|
/// // `ptr` is dangling, this is UB
|
||||||
|
/// ffi::PyUnicode_CheckExact(ptr)
|
||||||
|
/// };
|
||||||
|
/// # assert_eq!(isnt_a_pystring, 0);
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This happens because the pointer returned by `as_ptr` does not carry any lifetime information
|
||||||
|
/// and the Python object is dropped immediately after the `0xabad1dea_u32.into_py(py).as_ptr()`
|
||||||
|
/// expression is evaluated. To fix the problem, bind Python object to a local variable like earlier
|
||||||
|
/// to keep the Python object alive until the end of its scope.
|
||||||
pub trait AsPyPointer {
|
pub trait AsPyPointer {
|
||||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
/// Returns the underlying FFI pointer as a borrowed pointer.
|
||||||
fn as_ptr(&self) -> *mut ffi::PyObject;
|
fn as_ptr(&self) -> *mut ffi::PyObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This trait allows retrieving the underlying FFI pointer from Python objects.
|
/// Returns an owned pointer to a Python object.
|
||||||
|
///
|
||||||
|
/// The returned pointer will be valid until you decrease its reference count. It may be null
|
||||||
|
/// depending on the implementation.
|
||||||
|
/// It is your responsibility to decrease the reference count of the pointer to avoid leaking memory.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use pyo3::prelude::*;
|
||||||
|
/// use pyo3::IntoPyPointer;
|
||||||
|
/// use pyo3::types::PyString;
|
||||||
|
/// use pyo3::ffi;
|
||||||
|
///
|
||||||
|
/// Python::with_gil(|py| {
|
||||||
|
/// let s: Py<PyString> = "foo".into_py(py);
|
||||||
|
/// let ptr = s.into_ptr();
|
||||||
|
///
|
||||||
|
/// let is_really_a_pystring = unsafe { ffi::PyUnicode_CheckExact(ptr) };
|
||||||
|
/// assert_eq!(is_really_a_pystring, 1);
|
||||||
|
///
|
||||||
|
/// // Because we took ownership of the pointer,
|
||||||
|
/// // we must manually decrement it to avoid leaking memory
|
||||||
|
/// unsafe { ffi::Py_DECREF(ptr) };
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
pub trait IntoPyPointer {
|
pub trait IntoPyPointer {
|
||||||
/// Retrieves the underlying FFI pointer. Whether pointer owned or borrowed
|
/// Returns the underlying FFI pointer as an owned pointer.
|
||||||
/// depends on implementation.
|
///
|
||||||
|
/// If `self` has ownership of the underlying pointer, it will "steal" ownership of it.
|
||||||
fn into_ptr(self) -> *mut ffi::PyObject;
|
fn into_ptr(self) -> *mut ffi::PyObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,17 +246,32 @@ pub trait IntoPy<T>: Sized {
|
||||||
fn into_py(self, py: Python<'_>) -> T;
|
fn into_py(self, py: Python<'_>) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `FromPyObject` is implemented by various types that can be extracted from
|
/// Extract a type from a Python object.
|
||||||
/// a Python object reference.
|
|
||||||
///
|
///
|
||||||
/// Normal usage is through the helper methods `Py::extract` or `PyAny::extract`:
|
|
||||||
///
|
///
|
||||||
/// ```rust,ignore
|
/// Normal usage is through the `extract` methods on [`Py`] and [`PyAny`], which forward to this trait.
|
||||||
/// let obj: Py<PyAny> = ...;
|
|
||||||
/// let value: &TargetType = obj.extract(py)?;
|
|
||||||
///
|
///
|
||||||
/// let any: &PyAny = ...;
|
/// # Examples
|
||||||
/// let value: &TargetType = any.extract()?;
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use pyo3::prelude::*;
|
||||||
|
/// use pyo3::types::PyString;
|
||||||
|
///
|
||||||
|
/// # fn main() -> PyResult<()> {
|
||||||
|
/// Python::with_gil(|py| {
|
||||||
|
/// let obj: Py<PyString> = PyString::new(py, "blah").into();
|
||||||
|
///
|
||||||
|
/// // Straight from an owned reference
|
||||||
|
/// let s: &str = obj.extract(py)?;
|
||||||
|
/// # assert_eq!(s, "blah");
|
||||||
|
///
|
||||||
|
/// // Or from a borrowed reference
|
||||||
|
/// let obj: &PyString = obj.as_ref(py);
|
||||||
|
/// let s: &str = obj.extract()?;
|
||||||
|
/// # assert_eq!(s, "blah");
|
||||||
|
/// # Ok(())
|
||||||
|
/// })
|
||||||
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Note: depending on the implementation, the lifetime of the extracted result may
|
/// Note: depending on the implementation, the lifetime of the extracted result may
|
||||||
|
|
Loading…
Reference in New Issue