Refactor PyObjectAlloc

This commit is contained in:
konstin 2018-11-12 14:58:16 +01:00
parent cd23574d8a
commit d1de3338d1
5 changed files with 27 additions and 32 deletions

View File

@ -75,7 +75,7 @@ fn impl_class(
let extra = {
if let Some(freelist) = params.get("freelist") {
Some(quote! {
quote! {
impl ::pyo3::freelist::PyObjectWithFreeList for #cls {
#[inline]
fn get_free_list() -> &'static mut ::pyo3::freelist::FreeList<*mut ::pyo3::ffi::PyObject> {
@ -91,19 +91,21 @@ fn impl_class(
}
}
}
})
}
} else {
None
quote! {
impl ::pyo3::typeob::PyObjectAlloc for #cls {}
}
}
};
let extra = if !descriptors.is_empty() {
let ty = syn::parse_str(&cls.to_string()).expect("no name");
let desc_impls = impl_descriptors(&ty, descriptors);
Some(quote! {
quote! {
#desc_impls
#extra
})
}
} else {
extra
};

View File

@ -156,7 +156,7 @@ impl<T> Py<T> {
impl<T> Py<T>
where
T: PyTypeInfo,
T: PyTypeCreate,
{
/// Create new instance of T and move it under python management
/// Returns `Py<T>`.

View File

@ -195,30 +195,11 @@ pub(crate) unsafe fn pytype_drop<T: PyTypeInfo>(py: Python, obj: *mut ffi::PyObj
}
/// A Python object allocator that is usable as a base type for `#[pyclass]`
pub trait PyObjectAlloc: PyTypeInfo {
/// Allocates a new object (usually by calling ty->tp_alloc),
unsafe fn alloc(py: Python) -> PyResult<*mut ffi::PyObject>;
/// Calls the rust destructor for the object and frees the memory
/// (usually by calling ptr->ob_type->tp_free).
/// This function is used as tp_dealloc implementation.
unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject);
/// Calls the rust destructor for the object.
unsafe fn drop(_py: Python, _obj: *mut ffi::PyObject) {}
}
impl<T> PyObjectAlloc for T
where
T: PyTypeInfo,
{
#[allow(unconditional_recursion)]
/// Calls the rust destructor for the object.
default unsafe fn drop(py: Python, obj: *mut ffi::PyObject) {
pytype_drop::<Self>(py, obj);
}
default unsafe fn alloc(_py: Python) -> PyResult<*mut ffi::PyObject> {
///
/// All native types and all `#[pyclass]` types use the default functions, while
/// [PyObjectWithFreeList](crate::freelist::PyObjectWithFreeList) gets a special version.
pub trait PyObjectAlloc: PyTypeInfo + Sized {
unsafe fn alloc(_py: Python) -> PyResult<*mut ffi::PyObject> {
// TODO: remove this
<Self as PyTypeCreate>::init_type();
@ -229,7 +210,10 @@ where
Ok(obj)
}
default unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
/// Calls the rust destructor for the object and frees the memory
/// (usually by calling ptr->ob_type->tp_free).
/// This function is used as tp_dealloc implementation.
unsafe fn dealloc(py: Python, obj: *mut ffi::PyObject) {
Self::drop(py, obj);
#[cfg(Py_3)]
@ -257,6 +241,12 @@ where
}
}
}
#[allow(unconditional_recursion)]
/// Calls the rust destructor for the object.
unsafe fn drop(py: Python, obj: *mut ffi::PyObject) {
pytype_drop::<Self>(py, obj);
}
}
/// Python object types that have a corresponding type object.

View File

@ -126,6 +126,8 @@ macro_rules! pyobject_native_type_convert(
}
}
impl $crate::typeob::PyObjectAlloc for $name {}
impl<$($type_param,)*> $crate::typeob::PyTypeCreate for $name {
#[inline]
fn init_type() {}

View File

@ -14,6 +14,7 @@ use crate::types::{exceptions, PyDict, PyObjectRef, PyType};
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::str;
use PyObjectAlloc;
/// Represents a Python `module` object.
#[repr(transparent)]
@ -149,7 +150,7 @@ impl PyModule {
/// and adds the type to this module.
pub fn add_class<T>(&self) -> PyResult<()>
where
T: PyTypeInfo,
T: PyTypeInfo + PyObjectAlloc,
{
let ty = unsafe {
let ty = <T as PyTypeInfo>::type_object();