From 04f30c5971ee23fa1fc132f4b3a27a5944534b76 Mon Sep 17 00:00:00 2001 From: David Hewitt <1939362+davidhewitt@users.noreply.github.com> Date: Mon, 3 Feb 2020 07:34:42 +0000 Subject: [PATCH] Revisions from PR#751 --- guide/src/class.md | 15 +-------------- pyo3-derive-backend/src/pyclass.rs | 15 +-------------- src/pyclass.rs | 4 +++- src/type_object.rs | 20 +++++++++++++++++++- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/guide/src/class.md b/guide/src/class.md index ef37bd46343..47e787774bb 100644 --- a/guide/src/class.md +++ b/guide/src/class.md @@ -44,22 +44,9 @@ unsafe impl pyo3::PyTypeInfo for MyClass { #[inline] fn type_object() -> std::ptr::NonNull { - use std::ptr::NonNull; use pyo3::type_object::LazyTypeObject; static TYPE_OBJECT: LazyTypeObject = LazyTypeObject::new(); - TYPE_OBJECT.get_or_init(|| { - // automatically initialize the class on-demand - let gil = pyo3::Python::acquire_gil(); - let py = gil.python(); - let boxed = pyo3::pyclass::create_type_object::(py, Self::MODULE)?; - Ok(unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) }) - }) - .unwrap_or_else(|e| { - let gil = Python::acquire_gil(); - let py = gil.python(); - e.print(py); - panic!("An error occurred while initializing class {}", Self::NAME) - }) + TYPE_OBJECT.get_pyclass_type::() } } diff --git a/pyo3-derive-backend/src/pyclass.rs b/pyo3-derive-backend/src/pyclass.rs index 51f63d1c3b5..98f6202b173 100644 --- a/pyo3-derive-backend/src/pyclass.rs +++ b/pyo3-derive-backend/src/pyclass.rs @@ -383,22 +383,9 @@ fn impl_class( #[inline] fn type_object() -> std::ptr::NonNull { - use std::ptr::NonNull; use pyo3::type_object::LazyTypeObject; static TYPE_OBJECT: LazyTypeObject = LazyTypeObject::new(); - TYPE_OBJECT.get_or_init(|| { - // automatically initialize the class on-demand - let gil = pyo3::Python::acquire_gil(); - let py = gil.python(); - let boxed = pyo3::pyclass::create_type_object::(py, Self::MODULE)?; - Ok(unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) }) - }) - .unwrap_or_else(|e| { - let gil = Python::acquire_gil(); - let py = gil.python(); - e.print(py); - panic!("An error occurred while initializing class {}", Self::NAME) - }) + TYPE_OBJECT.get_pyclass_type::() } } diff --git a/src/pyclass.rs b/src/pyclass.rs index 5984251d151..7af34496958 100644 --- a/src/pyclass.rs +++ b/src/pyclass.rs @@ -253,13 +253,15 @@ where } #[cfg(not(Py_LIMITED_API))] -pub fn create_type_object( +pub(crate) fn create_type_object( py: Python, module_name: Option<&str>, ) -> PyResult> where T: PyClass, { + // Box (or some other heap allocation) is needed because PyType_Ready expects the type object + // to have a permanent memory address. let mut boxed = Box::new(ffi::PyTypeObject_INIT); let mut type_object = boxed.as_mut(); let base_type_object = ::type_object().as_ptr(); diff --git a/src/type_object.rs b/src/type_object.rs index fbe46f68ebb..9ca41dad111 100644 --- a/src/type_object.rs +++ b/src/type_object.rs @@ -3,6 +3,7 @@ use crate::err::PyResult; use crate::instance::Py; +use crate::pyclass::{create_type_object, PyClass}; use crate::pyclass_init::PyObjectInit; use crate::types::{PyAny, PyType}; use crate::{ffi, AsPyPointer, Python}; @@ -127,7 +128,8 @@ where } } -/// Type used to store type objects +/// Type used to store static type objects +#[doc(hidden)] pub struct LazyTypeObject { cell: OnceCell>, } @@ -145,6 +147,22 @@ impl LazyTypeObject { { Ok(*self.cell.get_or_try_init(constructor)?) } + + pub fn get_pyclass_type(&self) -> NonNull { + self.get_or_init(|| { + // automatically initialize the class on-demand + let gil = Python::acquire_gil(); + let py = gil.python(); + let boxed = create_type_object::(py, T::MODULE)?; + Ok(unsafe { NonNull::new_unchecked(Box::into_raw(boxed)) }) + }) + .unwrap_or_else(|e| { + let gil = Python::acquire_gil(); + let py = gil.python(); + e.print(py); + panic!("An error occurred while initializing class {}", T::NAME) + }) + } } // This is necessary for making static `LazyTypeObject`s