`#[pyclass]` objects can now be returned from rust functions

This commit is contained in:
konstin 2018-09-06 18:04:13 +02:00
parent f3c98ca7ba
commit ddc6313e74
3 changed files with 52 additions and 41 deletions

View File

@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## Unreleased ## Unreleased
### Added
* `#[pyclass]` objects can now be returned from rust functions
### Changed ### Changed
* Slowly removing specialization uses * Slowly removing specialization uses

View File

@ -86,65 +86,27 @@ fn impl_class(
let extra = if let Some(token) = token { let extra = if let Some(token) = token {
Some(quote! { Some(quote! {
impl ::pyo3::PyObjectWithToken for #cls { impl ::pyo3::PyObjectWithToken for #cls {
#[inline]
fn py<'p>(&'p self) -> ::pyo3::Python<'p> { fn py<'p>(&'p self) -> ::pyo3::Python<'p> {
self.#token.py() self.#token.py()
} }
} }
impl ::pyo3::ToPyObject for #cls {
#[inline]
fn to_object<'p>(&self, py: ::pyo3::Python<'p>) -> ::pyo3::PyObject {
unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
}
}
impl ::pyo3::ToBorrowedObject for #cls {
#[inline]
fn with_borrowed_ptr<F, R>(&self, _py: ::pyo3::Python, f: F) -> R
where F: FnOnce(*mut ::pyo3::ffi::PyObject) -> R
{
f(self.as_ptr())
}
}
impl<'a> ::pyo3::ToPyObject for &'a mut #cls {
#[inline]
fn to_object<'p>(&self, py: ::pyo3::Python<'p>) -> ::pyo3::PyObject {
unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
}
}
impl<'a> ::pyo3::ToBorrowedObject for &'a mut #cls {
#[inline]
fn with_borrowed_ptr<F, R>(&self, _py: ::pyo3::Python, f: F) -> R
where F: FnOnce(*mut ::pyo3::ffi::PyObject) -> R
{
f(self.as_ptr())
}
}
impl<'a> std::convert::From<&'a mut #cls> for &'a #cls impl<'a> std::convert::From<&'a mut #cls> for &'a #cls
{ {
fn from(ob: &'a mut #cls) -> Self { fn from(ob: &'a mut #cls) -> Self {
unsafe{std::mem::transmute(ob)} unsafe{std::mem::transmute(ob)}
} }
} }
impl ::pyo3::ToPyPointer for #cls {
#[inline]
fn as_ptr(&self) -> *mut ::pyo3::ffi::PyObject {
unsafe {
{self as *const _ as *mut u8}
.offset(-<#cls as ::pyo3::typeob::PyTypeInfo>::OFFSET) as *mut ::pyo3::ffi::PyObject
}
}
}
impl std::fmt::Debug for #cls { impl std::fmt::Debug for #cls {
fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
use ::pyo3::ObjectProtocol; use ::pyo3::ObjectProtocol;
let s = try!(self.repr().map_err(|_| std::fmt::Error)); let s = self.repr().map_err(|_| std::fmt::Error)?;
f.write_str(&s.to_string_lossy()) f.write_str(&s.to_string_lossy())
} }
} }
impl std::fmt::Display for #cls { impl std::fmt::Display for #cls {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
use ::pyo3::ObjectProtocol; use ::pyo3::ObjectProtocol;
let s = try!(self.str().map_err(|_| std::fmt::Error)); let s = self.str().map_err(|_| std::fmt::Error)?;
f.write_str(&s.to_string_lossy()) f.write_str(&s.to_string_lossy())
} }
} }
@ -263,6 +225,52 @@ fn impl_class(
} }
} }
// TBH I'm not sure what exactely this does and I'm sure there's a better way,
// but for now it works and it only safe code and it is required to return custom
// objects, so for now I'm keeping it
impl ::pyo3::IntoPyObject for #cls {
fn into_object<'p>(self, py: ::pyo3::Python<'p>) -> ::pyo3::PyObject {
::pyo3::Py::new(py, |_| self).unwrap().into_object(py)
}
}
impl ::pyo3::ToPyObject for #cls {
fn to_object<'p>(&self, py: ::pyo3::Python<'p>) -> ::pyo3::PyObject {
unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
}
}
impl ::pyo3::ToPyPointer for #cls {
fn as_ptr(&self) -> *mut ::pyo3::ffi::PyObject {
unsafe {
{self as *const _ as *mut u8}
.offset(-<#cls as ::pyo3::typeob::PyTypeInfo>::OFFSET) as *mut ::pyo3::ffi::PyObject
}
}
}
impl<'a> ::pyo3::ToPyObject for &'a mut #cls {
fn to_object<'p>(&self, py: ::pyo3::Python<'p>) -> ::pyo3::PyObject {
unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
}
}
impl ::pyo3::ToBorrowedObject for #cls {
fn with_borrowed_ptr<F, R>(&self, _py: ::pyo3::Python, f: F) -> R
where F: FnOnce(*mut ::pyo3::ffi::PyObject) -> R
{
f(self.as_ptr())
}
}
impl<'a> ::pyo3::ToBorrowedObject for &'a mut #cls {
fn with_borrowed_ptr<F, R>(&self, _py: ::pyo3::Python, f: F) -> R
where F: FnOnce(*mut ::pyo3::ffi::PyObject) -> R
{
f(self.as_ptr())
}
}
#extra #extra
} }
} }

View File

@ -93,7 +93,6 @@ impl<'a, T> IntoPyPointer for &'a T
where where
T: ToPyPointer, T: ToPyPointer,
{ {
#[inline]
fn into_ptr(self) -> *mut ffi::PyObject { fn into_ptr(self) -> *mut ffi::PyObject {
let ptr = self.as_ptr(); let ptr = self.as_ptr();
if !ptr.is_null() { if !ptr.is_null() {