Skip to content

Commit

Permalink
Revisions from PR#751
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Feb 3, 2020
1 parent 7531b9f commit 04f30c5
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 30 deletions.
15 changes: 1 addition & 14 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -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>()
}
}

Expand Down
15 changes: 1 addition & 14 deletions pyo3-derive-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>()
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
20 changes: 19 additions & 1 deletion src/type_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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>>,
}
Expand All @@ -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
Expand Down

0 comments on commit 04f30c5

Please sign in to comment.