only c classes only as base class
This commit is contained in:
parent
665a1da016
commit
afcfed492b
|
@ -59,8 +59,8 @@ so that they can benefit from a freelist. `XXX` is a number of items for free li
|
|||
participate in python garbage collector. If custom class contains references to other
|
||||
python object that can be collector `PyGCProtocol` trait has to be implemented.
|
||||
* `weakref` - adds support for python weak references
|
||||
* `base=xxx.YYY` - use custom base class. It is not possible to call constructor
|
||||
of base class at the moment. `xxx.YYY`, `xxx` - module name, `YYY` class name.
|
||||
* `base=BaseType` - use custom base class. BaseType is type which is
|
||||
implements `PyTypeInfo` trait.
|
||||
* `subclass` - adds subclass support so that Python classes can inherit from this class
|
||||
|
||||
|
||||
|
@ -105,12 +105,26 @@ By default `PyObject` is used as default base class. To override default base cl
|
|||
`base` parameter to `py::class` needs to be used. Value is full path to base class.
|
||||
|
||||
```rust
|
||||
#[py::class(base=asyncio.protocols.AbstractEventLoop)]
|
||||
class MyEventLoop {
|
||||
...
|
||||
|
||||
#[py::class]
|
||||
struct BaseClass {
|
||||
pub fn method(&self) -> PyResult<() {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[py::class(base=BaseClass)]
|
||||
struct MyEventLoop {
|
||||
fn method2(&self) -> PyResult<()> {
|
||||
self.get_super().method()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`ObjectProtocol` trait provide `get_super()` method. It returns reference to instance of
|
||||
parent class.
|
||||
|
||||
|
||||
## Object properties
|
||||
|
||||
Instance's `__dict__` attributes is not supported by pyo3 library. But it is
|
||||
|
|
|
@ -10,10 +10,8 @@ use utils;
|
|||
|
||||
|
||||
pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
||||
let (params, flags, base_cls) = parse_attribute(attr);
|
||||
let (params, flags, base) = parse_attribute(attr);
|
||||
let doc = utils::get_doc(&ast.attrs, true);
|
||||
|
||||
let base = syn::Ident::from("_pyo3::PyObjectRef");
|
||||
let mut token: Option<syn::Ident> = None;
|
||||
|
||||
match ast.body {
|
||||
|
@ -29,7 +27,7 @@ pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
|||
}
|
||||
|
||||
let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_CLS_{}", ast.ident));
|
||||
let tokens = impl_class(&ast.ident, &base, token, doc, params, flags, base_cls);
|
||||
let tokens = impl_class(&ast.ident, &base, token, doc, params, flags);
|
||||
|
||||
quote! {
|
||||
#[allow(non_upper_case_globals, unused_attributes,
|
||||
|
@ -45,8 +43,7 @@ pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
|||
|
||||
fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||
token: Option<syn::Ident>, doc: syn::Lit,
|
||||
params: HashMap<&'static str, syn::Ident>,
|
||||
flags: Vec<syn::Ident>, base_cls: Option<(String, String)>) -> Tokens {
|
||||
params: HashMap<&'static str, syn::Ident>, flags: Vec<syn::Ident>) -> Tokens {
|
||||
let cls_name = match params.get("name") {
|
||||
Some(name) => quote! { #name }.as_str().to_string(),
|
||||
None => quote! { #cls }.as_str().to_string()
|
||||
|
@ -113,7 +110,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
unsafe {
|
||||
{self as *const _ as *mut u8}
|
||||
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::offset())
|
||||
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET)
|
||||
as *mut ffi::PyObject
|
||||
}
|
||||
}
|
||||
|
@ -176,86 +173,27 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
syn::Ident::from("0")
|
||||
};
|
||||
|
||||
// base class
|
||||
let offset_code = if let Some((m, cls_name)) = base_cls {
|
||||
quote! {
|
||||
#[inline]
|
||||
unsafe fn base_type_object() -> &'static mut ffi::PyTypeObject {
|
||||
static mut TYPE_OBJECT: *mut ffi::PyTypeObject = 0 as *mut ffi::PyTypeObject;
|
||||
|
||||
if TYPE_OBJECT.is_null() {
|
||||
// load module
|
||||
let gil = _pyo3::Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
let imp = py.import(#m)
|
||||
.map_err(|e| e.print(py))
|
||||
.expect(format!(
|
||||
"Can not import module: {}", #m).as_ref());
|
||||
let cls = imp.get(#cls_name)
|
||||
.map_err(|e| e.print(py))
|
||||
.expect(format!(
|
||||
"Can not load exception class: {}.{}", #m, #cls_name).as_ref());
|
||||
TYPE_OBJECT = cls.into_ptr() as *mut ffi::PyTypeObject;
|
||||
}
|
||||
&mut *TYPE_OBJECT
|
||||
}
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
static mut OFFSET: isize = 0;
|
||||
unsafe {
|
||||
if OFFSET == 0 {
|
||||
// round base_size up to next multiple of align
|
||||
OFFSET = (
|
||||
((Self::base_type_object().tp_basicsize as usize) +
|
||||
std::mem::align_of::<#cls>()-1) /
|
||||
std::mem::align_of::<#cls>() * std::mem::align_of::<#cls>())
|
||||
as isize
|
||||
}
|
||||
OFFSET
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
static mut OFFSET: isize = 0;
|
||||
unsafe {
|
||||
if OFFSET == 0 {
|
||||
// round base_size up to next multiple of align
|
||||
OFFSET = (
|
||||
(<#base as _pyo3::typeob::PyTypeInfo>::size() +
|
||||
std::mem::align_of::<#cls>()-1) /
|
||||
std::mem::align_of::<#cls>() * std::mem::align_of::<#cls>())
|
||||
as isize
|
||||
}
|
||||
OFFSET
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
quote! {
|
||||
impl _pyo3::typeob::PyTypeInfo for #cls {
|
||||
type Type = #cls;
|
||||
type BaseType = #base;
|
||||
|
||||
const NAME: &'static str = #cls_name;
|
||||
const DESCRIPTION: &'static str = #doc;
|
||||
const FLAGS: usize = #(#flags)|*;
|
||||
|
||||
#[inline]
|
||||
fn size() -> usize {
|
||||
static mut SIZE: usize = 0;
|
||||
|
||||
unsafe {
|
||||
if SIZE == 0 {
|
||||
SIZE = Self::offset() as usize + std::mem::size_of::<#cls>() + #weakref;
|
||||
}
|
||||
SIZE
|
||||
}
|
||||
}
|
||||
|
||||
#offset_code
|
||||
const SIZE: usize = {
|
||||
Self::OFFSET as usize +
|
||||
std::mem::size_of::<#cls>() + #weakref
|
||||
};
|
||||
const OFFSET: isize = {
|
||||
// round base_size up to next multiple of align
|
||||
(
|
||||
(<#base as _pyo3::typeob::PyTypeInfo>::SIZE +
|
||||
std::mem::align_of::<#cls>() - 1) /
|
||||
std::mem::align_of::<#cls>() * std::mem::align_of::<#cls>()
|
||||
) as isize
|
||||
};
|
||||
|
||||
#[inline]
|
||||
unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
|
||||
|
@ -301,7 +239,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
|
||||
if checked {
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -316,7 +254,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||
{
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -328,14 +266,14 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
|
||||
{
|
||||
let ptr = (ob.as_ptr() as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
&*ptr
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self
|
||||
{
|
||||
let ptr = (ob.as_ptr() as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
@ -350,7 +288,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
|
||||
if checked {
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_mut().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -364,7 +302,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||
{
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::offset()) as *mut #cls;
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_mut().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -390,10 +328,10 @@ fn is_python_token(field: &syn::Field) -> bool {
|
|||
}
|
||||
|
||||
fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>,
|
||||
Vec<syn::Ident>, Option<(String, String)>) {
|
||||
Vec<syn::Ident>, syn::Ident) {
|
||||
let mut params = HashMap::new();
|
||||
let mut flags = vec![syn::Ident::from("0")];
|
||||
let mut base = None;
|
||||
let mut base = syn::Ident::from("_pyo3::PyObjectRef");
|
||||
|
||||
if let Ok(tts) = syn::parse_token_trees(&attr) {
|
||||
let mut elem = Vec::new();
|
||||
|
@ -499,11 +437,7 @@ fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>,
|
|||
el.to_tokens(&mut t);
|
||||
m += t.as_str().trim();
|
||||
}
|
||||
m = m.trim_matches('.').to_owned();
|
||||
let mut t = Tokens::new();
|
||||
elem[elem.len()-1].to_tokens(&mut t);
|
||||
let cls = t.as_str().trim().to_owned();
|
||||
base = Some((m, cls));
|
||||
base = syn::Ident::from(m.as_str());
|
||||
},
|
||||
_ => {
|
||||
println!("Unsupported parameter: {:?}", key);
|
||||
|
|
|
@ -81,14 +81,14 @@ impl<T> PyObjectAlloc<T> for T where T: PyObjectWithFreeList {
|
|||
ffi::PyType_GenericAlloc(<T as PyTypeInfo>::type_object(), 0)
|
||||
};
|
||||
|
||||
let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::offset()) as *mut T;
|
||||
let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::OFFSET) as *mut T;
|
||||
std::ptr::write(ptr, value);
|
||||
|
||||
Ok(obj)
|
||||
}
|
||||
|
||||
unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
|
||||
let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::offset()) as *mut T;
|
||||
let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::OFFSET) as *mut T;
|
||||
std::ptr::drop_in_place(ptr);
|
||||
|
||||
if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) {
|
||||
|
|
|
@ -206,14 +206,14 @@ impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo {
|
|||
#[inline]
|
||||
default fn as_ref(&self, _py: Python) -> &T {
|
||||
unsafe {
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(T::offset()) as *mut T;
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
ptr.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
default fn as_mut(&self, _py: Python) -> &mut T {
|
||||
unsafe {
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(T::offset()) as *mut T;
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
ptr.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@ use ffi;
|
|||
use err::{self, PyErr, PyResult};
|
||||
use python::{Python, ToPyPointer, PyDowncastFrom};
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyDict, PyString, PyIterator, PyType, PySuper};
|
||||
use objects::{PyObjectRef, PyDict, PyString, PyIterator, PyType};
|
||||
use conversion::{ToPyObject, ToBorrowedObject, IntoPyTuple, FromPyObject};
|
||||
use instance::PyObjectWithToken;
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
|
||||
/// Python object model helper methods
|
||||
|
@ -123,7 +124,8 @@ pub trait ObjectProtocol {
|
|||
|
||||
/// Gets the Python super object for this object.
|
||||
/// This is equivalent to the Python expression: 'super()'
|
||||
fn get_super(&self) -> &PySuper;
|
||||
fn get_super(&self) -> &<Self as PyTypeInfo>::BaseType
|
||||
where Self: PyTypeInfo, <Self as PyTypeInfo>::BaseType: PyDowncastFrom;
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
fn cast_as<'a, D>(&'a self) -> Option<&'a D>
|
||||
|
@ -355,8 +357,10 @@ impl<T> ObjectProtocol for T where T: PyObjectWithToken + ToPyPointer {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_super(&self) -> &PySuper {
|
||||
PySuper::new(self)
|
||||
fn get_super(&self) -> &<Self as PyTypeInfo>::BaseType
|
||||
where Self: PyTypeInfo, <Self as PyTypeInfo>::BaseType: PyDowncastFrom
|
||||
{
|
||||
unsafe { self.py().cast_from_borrowed_ptr(self.as_ptr()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#[macro_use] mod exc_impl;
|
||||
|
||||
pub use self::typeobject::PyType;
|
||||
pub use self::superobj::PySuper;
|
||||
pub use self::module::PyModule;
|
||||
pub use self::iterator::PyIterator;
|
||||
pub use self::boolobject::PyBool;
|
||||
|
@ -140,24 +139,11 @@ macro_rules! pyobject_nativetype(
|
|||
|
||||
impl $crate::typeob::PyTypeInfo for $name {
|
||||
type Type = ();
|
||||
type BaseType = $crate::PyObjectRef;
|
||||
|
||||
const NAME: &'static str = stringify!($name);
|
||||
|
||||
#[inline]
|
||||
fn size() -> usize {
|
||||
static mut SIZE: usize = 0;
|
||||
|
||||
unsafe {
|
||||
if SIZE == 0 {
|
||||
SIZE = $crate::std::mem::size_of::<$crate::ffi::PyObject>();
|
||||
}
|
||||
SIZE
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
0
|
||||
}
|
||||
const SIZE: usize = $crate::std::mem::size_of::<$crate::ffi::PyObject>();
|
||||
const OFFSET: isize = 0;
|
||||
|
||||
#[inline]
|
||||
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
||||
|
@ -266,7 +252,6 @@ mod slice;
|
|||
mod stringdata;
|
||||
mod stringutils;
|
||||
mod set;
|
||||
mod superobj;
|
||||
pub mod exc;
|
||||
|
||||
#[cfg(Py_3)]
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use std;
|
||||
|
||||
use ffi;
|
||||
use object::PyObject;
|
||||
use objects::{PyObjectRef, PyDict};
|
||||
use objectprotocol::ObjectProtocol;
|
||||
use conversion::IntoPyTuple;
|
||||
use python::{ToPyPointer, IntoPyPointer};
|
||||
use err::{self, PyResult};
|
||||
use instance::PyObjectWithToken;
|
||||
|
||||
/// Represents a reference to a Python `super object`.
|
||||
pub struct PySuper(PyObject);
|
||||
|
||||
pyobject_convert!(PySuper);
|
||||
pyobject_nativetype!(PySuper, PySuper_Type, PySuper_Check);
|
||||
|
||||
|
||||
impl PySuper {
|
||||
|
||||
pub fn new<T>(object: &T) -> &PySuper where T: PyObjectWithToken + ToPyPointer {
|
||||
// Create the arguments for super()
|
||||
unsafe {
|
||||
let o = object.py().from_borrowed_ptr(object.as_ptr());
|
||||
let args = (object.get_type(), o).into_tuple(object.py()).into_ptr();
|
||||
|
||||
// Creat the class super()
|
||||
let ptr = ffi::PyType_GenericNew(&mut ffi::PySuper_Type, args, std::ptr::null_mut());
|
||||
let oref = object.py().cast_from_ptr(ptr);
|
||||
|
||||
// call __init__ on super object
|
||||
if (*ffi::Py_TYPE(ptr)).tp_init.unwrap()(ptr, args, std::ptr::null_mut()) == -1 {
|
||||
err::panic_after_error()
|
||||
}
|
||||
oref
|
||||
}
|
||||
}
|
||||
|
||||
pub fn __new__<A>(&self, args: A, kwargs: Option<&PyDict>)
|
||||
-> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
self.call_method("__new__", args, kwargs)
|
||||
}
|
||||
|
||||
pub fn __init__<A>(&self, args: A, kwargs: Option<&PyDict>)
|
||||
-> PyResult<&PyObjectRef>
|
||||
where A: IntoPyTuple
|
||||
{
|
||||
self.call_method("__init__", args, kwargs)
|
||||
}
|
||||
}
|
|
@ -27,24 +27,17 @@ pub trait PyTypeInfo {
|
|||
/// Class doc string
|
||||
const DESCRIPTION: &'static str = "\0";
|
||||
|
||||
/// Type flags (ie PyType_GC, PyType_WeakRef)
|
||||
const FLAGS: usize = 0;
|
||||
|
||||
/// Size of the rust PyObject structure (PyObject + rust structure)
|
||||
fn size() -> usize;
|
||||
const SIZE: usize;
|
||||
|
||||
/// `Type` instance offset inside PyObject structure
|
||||
fn offset() -> isize;
|
||||
const OFFSET: isize;
|
||||
|
||||
/// Type flags (ie PY_TYPE_FLAG_GC, PY_TYPE_FLAG_WEAKREF)
|
||||
const FLAGS: usize = 0;
|
||||
|
||||
/// Base class
|
||||
unsafe fn base_type_object() -> &'static mut ffi::PyTypeObject {
|
||||
static mut TYPE_OBJECT: *mut ffi::PyTypeObject = std::ptr::null_mut();
|
||||
|
||||
if TYPE_OBJECT.is_null() {
|
||||
TYPE_OBJECT = &mut ffi::PyBaseObject_Type;
|
||||
}
|
||||
&mut *TYPE_OBJECT
|
||||
}
|
||||
type BaseType: PyTypeInfo;
|
||||
|
||||
/// PyTypeObject instance for this type
|
||||
unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
|
||||
|
@ -66,20 +59,13 @@ pub const PY_TYPE_FLAG_BASETYPE: usize = 1<<2;
|
|||
|
||||
impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
||||
type Type = T::Type;
|
||||
type BaseType = T::BaseType;
|
||||
const NAME: &'static str = T::NAME;
|
||||
const DESCRIPTION: &'static str = T::DESCRIPTION;
|
||||
const SIZE: usize = T::SIZE;
|
||||
const OFFSET: isize = T::OFFSET;
|
||||
const FLAGS: usize = T::FLAGS;
|
||||
|
||||
#[inline]
|
||||
default fn size() -> usize {
|
||||
<T as PyTypeInfo>::size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn offset() -> isize {
|
||||
<T as PyTypeInfo>::offset()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default unsafe fn type_object() -> &'static mut ffi::PyTypeObject {
|
||||
<T as PyTypeInfo>::type_object()
|
||||
|
@ -113,14 +99,14 @@ impl<T> PyObjectAlloc<T> for T where T : PyTypeInfo {
|
|||
|
||||
let obj = ffi::PyType_GenericAlloc(T::type_object(), 0);
|
||||
|
||||
let ptr = (obj as *mut u8).offset(T::offset()) as *mut T;
|
||||
let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
std::ptr::write(ptr, value);
|
||||
|
||||
Ok(obj)
|
||||
}
|
||||
|
||||
default unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
|
||||
let ptr = (obj as *mut u8).offset(T::offset()) as *mut T;
|
||||
let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
std::ptr::drop_in_place(ptr);
|
||||
|
||||
if ffi::PyObject_CallFinalizerFromDealloc(obj) < 0 {
|
||||
|
@ -179,20 +165,23 @@ pub fn initialize_type<'p, T>(py: Python<'p>, module_name: Option<&str>) -> PyRe
|
|||
"Module name/type name must not contain NUL byte").into_raw();
|
||||
|
||||
let type_object: &mut ffi::PyTypeObject = unsafe{&mut *T::type_object()};
|
||||
let base_type_object: &mut ffi::PyTypeObject = unsafe{
|
||||
&mut *<T::BaseType as PyTypeInfo>::type_object()};
|
||||
|
||||
type_object.tp_name = name;
|
||||
type_object.tp_doc = T::DESCRIPTION.as_ptr() as *const _;
|
||||
type_object.tp_base = unsafe{<T as PyTypeInfo>::base_type_object()};
|
||||
type_object.tp_base = base_type_object;
|
||||
|
||||
// dealloc
|
||||
type_object.tp_dealloc = Some(tp_dealloc_callback::<T>);
|
||||
|
||||
// type size
|
||||
type_object.tp_basicsize = <T as PyTypeInfo>::size() as ffi::Py_ssize_t;
|
||||
type_object.tp_basicsize = <T as PyTypeInfo>::SIZE as ffi::Py_ssize_t;
|
||||
|
||||
// weakref support (check py3cls::py_class::impl_class)
|
||||
if T::FLAGS & PY_TYPE_FLAG_WEAKREF != 0 {
|
||||
type_object.tp_weaklistoffset =
|
||||
(T::size() - std::mem::size_of::<*const ffi::PyObject>()) as isize;
|
||||
(T::SIZE - std::mem::size_of::<*const ffi::PyObject>()) as isize;
|
||||
}
|
||||
|
||||
// GC support
|
||||
|
|
Loading…
Reference in New Issue