Revisions from PR#751

This commit is contained in:
David Hewitt 2020-02-03 07:34:42 +00:00
parent 7531b9fb07
commit 04f30c5971
4 changed files with 24 additions and 30 deletions

View File

@ -44,22 +44,9 @@ unsafe impl pyo3::PyTypeInfo for MyClass {
#[inline]
fn type_object() -> std::ptr::NonNull<pyo3::ffi::PyTypeObject> {
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::<Self>(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::<Self>()
}
}

View File

@ -383,22 +383,9 @@ fn impl_class(
#[inline]
fn type_object() -> std::ptr::NonNull<pyo3::ffi::PyTypeObject> {
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::<Self>(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::<Self>()
}
}

View File

@ -253,13 +253,15 @@ where
}
#[cfg(not(Py_LIMITED_API))]
pub fn create_type_object<T>(
pub(crate) fn create_type_object<T>(
py: Python,
module_name: Option<&str>,
) -> PyResult<Box<ffi::PyTypeObject>>
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 = <T::BaseType as PyTypeInfo>::type_object().as_ptr();

View File

@ -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<NonNull<ffi::PyTypeObject>>,
}
@ -145,6 +147,22 @@ impl LazyTypeObject {
{
Ok(*self.cell.get_or_try_init(constructor)?)
}
pub fn get_pyclass_type<T: PyClass>(&self) -> NonNull<ffi::PyTypeObject> {
self.get_or_init(|| {
// automatically initialize the class on-demand
let gil = Python::acquire_gil();
let py = gil.python();
let boxed = create_type_object::<T>(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