use const_fn for type size and offset calculation
This commit is contained in:
parent
2ee6419464
commit
98bdf63a4d
|
@ -1,10 +1,11 @@
|
|||
# Python Class
|
||||
|
||||
Python class generation is powered by unstable [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html) and
|
||||
[Specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) features, so you need to turn on `proc_macro` and `specialization` features:
|
||||
[Specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) and [Const fn](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md)
|
||||
features, so you need to turn on `proc_macro` and `specialization` features:
|
||||
|
||||
```rust
|
||||
#![feature(proc_macro, specialization)]
|
||||
#![feature(proc_macro, specialization, const_fn)]
|
||||
|
||||
extern crate pyo3;
|
||||
```
|
||||
|
|
|
@ -106,9 +106,9 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
impl _pyo3::ToPyPointer for #cls {
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
{self as *const _ as *mut u8}.offset(-offset) as *mut ffi::PyObject
|
||||
{self as *const _ as *mut u8}
|
||||
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut ffi::PyObject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -164,19 +164,12 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
const NAME: &'static str = #cls_name;
|
||||
const DESCRIPTION: &'static str = #doc;
|
||||
|
||||
#[inline]
|
||||
fn size() -> usize {
|
||||
Self::offset() as usize + std::mem::size_of::<#cls>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
let align = std::mem::align_of::<#cls>();
|
||||
let bs = <#base as _pyo3::typeob::PyTypeInfo>::size();
|
||||
|
||||
const SIZE: usize = Self::OFFSET as usize + std::mem::size_of::<#cls>();
|
||||
const OFFSET: isize = {
|
||||
// round base_size up to next multiple of align
|
||||
((bs + align - 1) / align * align) as isize
|
||||
}
|
||||
((<#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 {
|
||||
|
@ -218,8 +211,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
||||
|
||||
if checked {
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls;
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -233,8 +226,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
let ptr = ob.as_ptr();
|
||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||
{
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls;
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -245,15 +238,15 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
#[inline]
|
||||
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
|
||||
{
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls;
|
||||
let ptr = (ob.as_ptr() as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
&*ptr
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self
|
||||
{
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls;
|
||||
let ptr = (ob.as_ptr() as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
&mut *ptr
|
||||
}
|
||||
}
|
||||
|
@ -267,8 +260,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
||||
|
||||
if checked {
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls;
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_mut().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
@ -281,8 +274,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
|||
let ptr = ob.as_ptr();
|
||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
||||
{
|
||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
||||
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls;
|
||||
let ptr = (ptr as *mut u8)
|
||||
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||
Some(ptr.as_mut().unwrap())
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -81,15 +81,14 @@ impl<T> PyObjectAlloc<T> for T where T: PyObjectWithFreeList {
|
|||
ffi::PyType_GenericAlloc(<T as PyTypeInfo>::type_object(), 0)
|
||||
};
|
||||
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
let ptr = (obj as *mut u8).offset(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) {
|
||||
|
|
|
@ -205,17 +205,15 @@ impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo {
|
|||
|
||||
#[inline]
|
||||
default fn as_ref(&self, _py: Python) -> &T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(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 {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(offset) as *mut T;
|
||||
let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
ptr.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,15 +138,9 @@ macro_rules! pyobject_nativetype(
|
|||
impl $crate::typeob::PyTypeInfo for $name {
|
||||
type Type = ();
|
||||
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 {
|
||||
$crate::std::mem::size_of::<$crate::ffi::PyObject>()
|
||||
}
|
||||
#[inline]
|
||||
fn offset() -> isize {
|
||||
0
|
||||
}
|
||||
#[inline]
|
||||
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
|
||||
&mut $crate::ffi::$typeobject
|
||||
|
|
|
@ -18,16 +18,18 @@ use class::methods::PyMethodDefType;
|
|||
pub trait PyTypeInfo {
|
||||
/// Type of objects to store in PyObject struct
|
||||
type Type;
|
||||
|
||||
/// Class name
|
||||
const NAME: &'static str;
|
||||
|
||||
/// Class doc string
|
||||
const DESCRIPTION: &'static str = "\0";
|
||||
|
||||
/// Size of the PyObject structure
|
||||
fn size() -> usize;
|
||||
/// Size of the rust PyObject structure (PyObject + rust structure)
|
||||
const SIZE: usize;
|
||||
|
||||
/// `Type` instance offset inside PyObject structure
|
||||
fn offset() -> isize;
|
||||
const OFFSET: isize;
|
||||
|
||||
/// PyTypeObject instance for this type
|
||||
unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
|
||||
|
@ -41,16 +43,9 @@ pub trait PyTypeInfo {
|
|||
impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
||||
type Type = T::Type;
|
||||
const NAME: &'static str = T::NAME;
|
||||
|
||||
#[inline]
|
||||
default fn size() -> usize {
|
||||
<T as PyTypeInfo>::size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn offset() -> isize {
|
||||
<T as PyTypeInfo>::offset()
|
||||
}
|
||||
const DESCRIPTION: &'static str = T::DESCRIPTION;
|
||||
const SIZE: usize = T::SIZE;
|
||||
const OFFSET: isize = T::OFFSET;
|
||||
|
||||
#[inline]
|
||||
default unsafe fn type_object() -> &'static mut ffi::PyTypeObject {
|
||||
|
@ -81,20 +76,18 @@ impl<T> PyObjectAlloc<T> for T where T : PyTypeInfo {
|
|||
|
||||
default unsafe fn alloc(py: Python, value: T) -> PyResult<*mut ffi::PyObject> {
|
||||
// TODO: remove this
|
||||
<T as PyTypeObject>::init_type(py);
|
||||
T::init_type(py);
|
||||
|
||||
let obj = ffi::PyType_GenericAlloc(
|
||||
<Self as PyTypeInfo>::type_object(), 0);
|
||||
let obj = ffi::PyType_GenericAlloc(T::type_object(), 0);
|
||||
|
||||
let offset = <Self as PyTypeInfo>::offset();
|
||||
let ptr = (obj as *mut u8).offset(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(<Self as PyTypeInfo>::offset()) as *mut T;
|
||||
let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
|
||||
std::ptr::drop_in_place(ptr);
|
||||
|
||||
let ty = ffi::Py_TYPE(obj);
|
||||
|
@ -165,7 +158,7 @@ pub fn initialize_type<'p, T>(py: Python<'p>,
|
|||
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;
|
||||
|
||||
// GC support
|
||||
<T as class::gc::PyGCProtocolImpl>::update_type_object(type_object);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#![allow(dead_code, unused_variables)]
|
||||
#![feature(proc_macro, specialization)]
|
||||
#![feature(proc_macro, specialization, const_fn)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(proc_macro, specialization)]
|
||||
#![feature(proc_macro, specialization, const_fn)]
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![feature(proc_macro, specialization)]
|
||||
#![feature(proc_macro, specialization, const_fn)]
|
||||
#![allow(dead_code, unused_variables)]
|
||||
|
||||
extern crate pyo3;
|
||||
|
|
Loading…
Reference in New Issue