From ddc6313e74eeb4dfff38aa5ef5efde9e15cc4261 Mon Sep 17 00:00:00 2001 From: konstin Date: Thu, 6 Sep 2018 18:04:13 +0200 Subject: [PATCH] `#[pyclass]` objects can now be returned from rust functions --- CHANGELOG.md | 4 ++ pyo3-derive-backend/src/py_class.rs | 88 ++++++++++++++++------------- src/python.rs | 1 - 3 files changed, 52 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1eb21f6..ea82bffa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased +### Added + + * `#[pyclass]` objects can now be returned from rust functions + ### Changed * Slowly removing specialization uses diff --git a/pyo3-derive-backend/src/py_class.rs b/pyo3-derive-backend/src/py_class.rs index facfd242..fc0d02f0 100644 --- a/pyo3-derive-backend/src/py_class.rs +++ b/pyo3-derive-backend/src/py_class.rs @@ -86,65 +86,27 @@ fn impl_class( let extra = if let Some(token) = token { Some(quote! { impl ::pyo3::PyObjectWithToken for #cls { - #[inline] fn py<'p>(&'p self) -> ::pyo3::Python<'p> { 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(&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(&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 { fn from(ob: &'a mut #cls) -> Self { 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 { fn fmt(&self, f : &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 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()) } } impl std::fmt::Display for #cls { fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { 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()) } } @@ -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(&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(&self, _py: ::pyo3::Python, f: F) -> R + where F: FnOnce(*mut ::pyo3::ffi::PyObject) -> R + { + f(self.as_ptr()) + } + } + #extra } } diff --git a/src/python.rs b/src/python.rs index 31915751..bc80a0bc 100644 --- a/src/python.rs +++ b/src/python.rs @@ -93,7 +93,6 @@ impl<'a, T> IntoPyPointer for &'a T where T: ToPyPointer, { - #[inline] fn into_ptr(self) -> *mut ffi::PyObject { let ptr = self.as_ptr(); if !ptr.is_null() {