add base support for inheritance
This commit is contained in:
parent
8227ce81e2
commit
d567817035
|
@ -59,6 +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
|
participate in python garbage collector. If custom class contains references to other
|
||||||
python object that can be collector `PyGCProtocol` trait has to be implemented.
|
python object that can be collector `PyGCProtocol` trait has to be implemented.
|
||||||
* `weakref` - adds support for python weak references
|
* `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.
|
||||||
|
|
||||||
|
|
||||||
## Constructor
|
## Constructor
|
||||||
|
|
|
@ -4,13 +4,13 @@ use std;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use syn;
|
use syn;
|
||||||
use quote::Tokens;
|
use quote::{Tokens, ToTokens};
|
||||||
|
|
||||||
use utils;
|
use utils;
|
||||||
|
|
||||||
|
|
||||||
pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
||||||
let (params, flags) = parse_attribute(attr);
|
let (params, flags, base_cls) = parse_attribute(attr);
|
||||||
let doc = utils::get_doc(&ast.attrs, true);
|
let doc = utils::get_doc(&ast.attrs, true);
|
||||||
|
|
||||||
let base = syn::Ident::from("_pyo3::PyObjectRef");
|
let base = syn::Ident::from("_pyo3::PyObjectRef");
|
||||||
|
@ -29,7 +29,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 dummy_const = syn::Ident::new(format!("_IMPL_PYO3_CLS_{}", ast.ident));
|
||||||
let tokens = impl_class(&ast.ident, &base, token, doc, params, flags);
|
let tokens = impl_class(&ast.ident, &base, token, doc, params, flags, base_cls);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[allow(non_upper_case_globals, unused_attributes,
|
#[allow(non_upper_case_globals, unused_attributes,
|
||||||
|
@ -45,7 +45,8 @@ pub fn build_py_class(ast: &mut syn::DeriveInput, attr: String) -> Tokens {
|
||||||
|
|
||||||
fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
token: Option<syn::Ident>, doc: syn::Lit,
|
token: Option<syn::Ident>, doc: syn::Lit,
|
||||||
params: HashMap<&'static str, syn::Ident>, flags: Vec<syn::Ident>) -> Tokens {
|
params: HashMap<&'static str, syn::Ident>,
|
||||||
|
flags: Vec<syn::Ident>, base_cls: Option<(String, String)>) -> Tokens {
|
||||||
let cls_name = match params.get("name") {
|
let cls_name = match params.get("name") {
|
||||||
Some(name) => quote! { #name }.as_str().to_string(),
|
Some(name) => quote! { #name }.as_str().to_string(),
|
||||||
None => quote! { #cls }.as_str().to_string()
|
None => quote! { #cls }.as_str().to_string()
|
||||||
|
@ -112,7 +113,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||||
unsafe {
|
unsafe {
|
||||||
{self as *const _ as *mut u8}
|
{self as *const _ as *mut u8}
|
||||||
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut ffi::PyObject
|
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::offset())
|
||||||
|
as *mut ffi::PyObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -174,21 +176,85 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
syn::Ident::from("0")
|
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)
|
||||||
|
.expect(format!(
|
||||||
|
"Can not import module: {}", #m).as_ref());
|
||||||
|
let cls = imp.get(#cls_name)
|
||||||
|
.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! {
|
quote! {
|
||||||
impl _pyo3::typeob::PyTypeInfo for #cls {
|
impl _pyo3::typeob::PyTypeInfo for #cls {
|
||||||
type Type = #cls;
|
type Type = #cls;
|
||||||
const NAME: &'static str = #cls_name;
|
const NAME: &'static str = #cls_name;
|
||||||
const DESCRIPTION: &'static str = #doc;
|
const DESCRIPTION: &'static str = #doc;
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
const FLAGS: usize = #(#flags)|*;
|
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
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
|
unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
|
||||||
static mut TYPE_OBJECT: _pyo3::ffi::PyTypeObject = _pyo3::ffi::PyTypeObject_INIT;
|
static mut TYPE_OBJECT: _pyo3::ffi::PyTypeObject = _pyo3::ffi::PyTypeObject_INIT;
|
||||||
|
@ -233,7 +299,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
|
|
||||||
if checked {
|
if checked {
|
||||||
let ptr = (ptr as *mut u8)
|
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())
|
Some(ptr.as_ref().unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -248,7 +314,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||||
{
|
{
|
||||||
let ptr = (ptr as *mut u8)
|
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())
|
Some(ptr.as_ref().unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -260,14 +326,14 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
|
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
|
||||||
{
|
{
|
||||||
let ptr = (ob.as_ptr() as *mut u8)
|
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
|
&*ptr
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self
|
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self
|
||||||
{
|
{
|
||||||
let ptr = (ob.as_ptr() as *mut u8)
|
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
|
&mut *ptr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +348,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
|
|
||||||
if checked {
|
if checked {
|
||||||
let ptr = (ptr as *mut u8)
|
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())
|
Some(ptr.as_mut().unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -296,7 +362,7 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||||
{
|
{
|
||||||
let ptr = (ptr as *mut u8)
|
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())
|
Some(ptr.as_mut().unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -321,9 +387,11 @@ fn is_python_token(field: &syn::Field) -> bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>, Vec<syn::Ident>) {
|
fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>,
|
||||||
|
Vec<syn::Ident>, Option<(String, String)>) {
|
||||||
let mut params = HashMap::new();
|
let mut params = HashMap::new();
|
||||||
let mut flags = vec![syn::Ident::from("0")];
|
let mut flags = vec![syn::Ident::from("0")];
|
||||||
|
let mut base = None;
|
||||||
|
|
||||||
if let Ok(tts) = syn::parse_token_trees(&attr) {
|
if let Ok(tts) = syn::parse_token_trees(&attr) {
|
||||||
let mut elem = Vec::new();
|
let mut elem = Vec::new();
|
||||||
|
@ -419,7 +487,17 @@ fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>, Vec<syn:
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"base" => {
|
"base" => {
|
||||||
|
let mut m = String::new();
|
||||||
|
for el in elem[2..elem.len()-1].iter() {
|
||||||
|
let mut t = Tokens::new();
|
||||||
|
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));
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
println!("Unsupported parameter: {:?}", key);
|
println!("Unsupported parameter: {:?}", key);
|
||||||
|
@ -428,5 +506,5 @@ fn parse_attribute(attr: String) -> (HashMap<&'static str, syn::Ident>, Vec<syn:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
(params, flags)
|
(params, flags, base)
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,14 +81,14 @@ impl<T> PyObjectAlloc<T> for T where T: PyObjectWithFreeList {
|
||||||
ffi::PyType_GenericAlloc(<T as PyTypeInfo>::type_object(), 0)
|
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);
|
std::ptr::write(ptr, value);
|
||||||
|
|
||||||
Ok(obj)
|
Ok(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
|
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);
|
std::ptr::drop_in_place(ptr);
|
||||||
|
|
||||||
if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) {
|
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]
|
#[inline]
|
||||||
default fn as_ref(&self, _py: Python) -> &T {
|
default fn as_ref(&self, _py: Python) -> &T {
|
||||||
unsafe {
|
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()
|
ptr.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
default fn as_mut(&self, _py: Python) -> &mut T {
|
default fn as_mut(&self, _py: Python) -> &mut T {
|
||||||
unsafe {
|
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()
|
ptr.as_mut().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,8 +140,23 @@ macro_rules! pyobject_nativetype(
|
||||||
impl $crate::typeob::PyTypeInfo for $name {
|
impl $crate::typeob::PyTypeInfo for $name {
|
||||||
type Type = ();
|
type Type = ();
|
||||||
const NAME: &'static str = stringify!($name);
|
const NAME: &'static str = stringify!($name);
|
||||||
const SIZE: usize = $crate::std::mem::size_of::<$crate::ffi::PyObject>();
|
|
||||||
const OFFSET: isize = 0;
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
||||||
|
|
|
@ -26,15 +26,25 @@ pub trait PyTypeInfo {
|
||||||
/// Class doc string
|
/// Class doc string
|
||||||
const DESCRIPTION: &'static str = "\0";
|
const DESCRIPTION: &'static str = "\0";
|
||||||
|
|
||||||
/// Size of the rust PyObject structure (PyObject + rust structure)
|
|
||||||
const SIZE: usize;
|
|
||||||
|
|
||||||
/// `Type` instance offset inside PyObject structure
|
|
||||||
const OFFSET: isize;
|
|
||||||
|
|
||||||
/// Type flags (ie PyType_GC, PyType_WeakRef)
|
/// Type flags (ie PyType_GC, PyType_WeakRef)
|
||||||
const FLAGS: usize = 0;
|
const FLAGS: usize = 0;
|
||||||
|
|
||||||
|
/// Size of the rust PyObject structure (PyObject + rust structure)
|
||||||
|
fn size() -> usize;
|
||||||
|
|
||||||
|
/// `Type` instance offset inside PyObject structure
|
||||||
|
fn offset() -> isize;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
}
|
||||||
|
|
||||||
/// PyTypeObject instance for this type
|
/// PyTypeObject instance for this type
|
||||||
unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
|
unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
|
||||||
|
|
||||||
|
@ -54,10 +64,18 @@ impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
||||||
type Type = T::Type;
|
type Type = T::Type;
|
||||||
const NAME: &'static str = T::NAME;
|
const NAME: &'static str = T::NAME;
|
||||||
const DESCRIPTION: &'static str = T::DESCRIPTION;
|
const DESCRIPTION: &'static str = T::DESCRIPTION;
|
||||||
const SIZE: usize = T::SIZE;
|
|
||||||
const OFFSET: isize = T::OFFSET;
|
|
||||||
const FLAGS: usize = T::FLAGS;
|
const FLAGS: usize = T::FLAGS;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn size() -> usize {
|
||||||
|
<T as PyTypeInfo>::size()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
default fn offset() -> isize {
|
||||||
|
<T as PyTypeInfo>::offset()
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
default unsafe fn type_object() -> &'static mut ffi::PyTypeObject {
|
default unsafe fn type_object() -> &'static mut ffi::PyTypeObject {
|
||||||
<T as PyTypeInfo>::type_object()
|
<T as PyTypeInfo>::type_object()
|
||||||
|
@ -91,14 +109,14 @@ impl<T> PyObjectAlloc<T> for T where T : PyTypeInfo {
|
||||||
|
|
||||||
let obj = ffi::PyType_GenericAlloc(T::type_object(), 0);
|
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);
|
std::ptr::write(ptr, value);
|
||||||
|
|
||||||
Ok(obj)
|
Ok(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
default unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
|
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);
|
std::ptr::drop_in_place(ptr);
|
||||||
|
|
||||||
let ty = ffi::Py_TYPE(obj);
|
let ty = ffi::Py_TYPE(obj);
|
||||||
|
@ -165,17 +183,18 @@ pub fn initialize_type<'p, T>(py: Python<'p>, module_name: Option<&str>) -> PyRe
|
||||||
let type_object: &mut ffi::PyTypeObject = unsafe{&mut *T::type_object()};
|
let type_object: &mut ffi::PyTypeObject = unsafe{&mut *T::type_object()};
|
||||||
type_object.tp_name = name;
|
type_object.tp_name = name;
|
||||||
type_object.tp_doc = T::DESCRIPTION.as_ptr() as *const _;
|
type_object.tp_doc = T::DESCRIPTION.as_ptr() as *const _;
|
||||||
|
type_object.tp_base = unsafe{<T as PyTypeInfo>::base_type_object()};
|
||||||
|
|
||||||
// dealloc
|
// dealloc
|
||||||
type_object.tp_dealloc = Some(tp_dealloc_callback::<T>);
|
type_object.tp_dealloc = Some(tp_dealloc_callback::<T>);
|
||||||
|
|
||||||
// type size
|
// 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)
|
// weakref support (check py3cls::py_class::impl_class)
|
||||||
if T::FLAGS & PY_TYPE_FLAG_WEAKREF != 0 {
|
if T::FLAGS & PY_TYPE_FLAG_WEAKREF != 0 {
|
||||||
type_object.tp_weaklistoffset =
|
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
|
// GC support
|
||||||
|
@ -243,6 +262,9 @@ pub fn initialize_type<'p, T>(py: Python<'p>, module_name: Option<&str>) -> PyRe
|
||||||
|
|
||||||
// set type flags
|
// set type flags
|
||||||
py_class_flags::<T>(type_object);
|
py_class_flags::<T>(type_object);
|
||||||
|
if type_object.tp_base != unsafe{std::mem::transmute(&ffi::PyBaseObject_Type)} {
|
||||||
|
type_object.tp_flags = type_object.tp_flags | ffi::Py_TPFLAGS_HEAPTYPE
|
||||||
|
}
|
||||||
|
|
||||||
// register type object
|
// register type object
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -281,7 +303,7 @@ fn py_class_flags<T: PyTypeInfo>(type_object: &mut ffi::PyTypeObject) {
|
||||||
if type_object.tp_traverse != None || type_object.tp_clear != None ||
|
if type_object.tp_traverse != None || type_object.tp_clear != None ||
|
||||||
T::FLAGS & PY_TYPE_FLAG_GC != 0
|
T::FLAGS & PY_TYPE_FLAG_GC != 0
|
||||||
{
|
{
|
||||||
type_object.tp_flags = ffi::Py_TPFLAGS_DEFAULT | ffi::Py_TPFLAGS_HAVE_GC;
|
type_object.tp_flags = ffi::Py_TPFLAGS_DEFAULT | ffi::Py_TPFLAGS_HAVE_GC;
|
||||||
} else {
|
} else {
|
||||||
type_object.tp_flags = ffi::Py_TPFLAGS_DEFAULT;
|
type_object.tp_flags = ffi::Py_TPFLAGS_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue