diff --git a/src/instance.rs b/src/instance.rs index 024a9fe5b51..5f054d0d2d4 100644 --- a/src/instance.rs +++ b/src/instance.rs @@ -465,6 +465,13 @@ impl<'py, T> Bound<'py, T> { unsafe { Py::from_non_null(non_null) } } + /// Removes the connection for this `Bound` from the GIL, allowing + /// it to cross thread boundaries, without transferring ownership. + #[inline] + pub fn as_unbound(&self) -> &Py { + &self.1 + } + /// Casts this `Bound` as the corresponding "GIL Ref" type. /// /// This is a helper to be used for migration from the deprecated "GIL Refs" API. @@ -521,11 +528,11 @@ impl<'py, T> Borrowed<'_, 'py, T> { /// # fn main() -> PyResult<()> { /// Python::with_gil(|py| -> PyResult<()> { /// let tuple = PyTuple::new_bound(py, [1, 2, 3]); - /// + /// /// // borrows from `tuple`, so can only be /// // used while `tuple` stays alive /// let borrowed = tuple.get_borrowed_item(0)?; - /// + /// /// // creates a new owned reference, which /// // can be used indendently of `tuple` /// let bound = borrowed.to_owned(); @@ -1960,8 +1967,8 @@ impl PyObject { mod tests { use super::{Bound, Py, PyObject}; use crate::types::any::PyAnyMethods; - use crate::types::PyCapsule; use crate::types::{dict::IntoPyDict, PyDict, PyString}; + use crate::types::{PyCapsule, PyStringMethods}; use crate::{ffi, Borrowed, PyAny, PyNativeType, PyResult, Python, ToPyObject}; #[test] @@ -2161,6 +2168,20 @@ a = A() }); } + #[test] + fn test_bound_py_conversions() { + Python::with_gil(|py| { + let obj: Bound<'_, PyString> = PyString::new_bound(py, "hello world"); + let obj_unbound: &Py = obj.as_unbound(); + let _: &Bound<'_, PyString> = obj_unbound.bind(py); + + let obj_unbound: Py = obj.unbind(); + let obj: Bound<'_, PyString> = obj_unbound.into_bound(py); + + assert_eq!(obj.to_cow().unwrap(), "hello world"); + }); + } + #[test] fn bound_from_borrowed_ptr_constructors() { // More detailed tests of the underlying semantics in pycell.rs