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
|
||||||
|
|
||||||
Python class generation is powered by unstable [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html) and
|
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
|
```rust
|
||||||
#![feature(proc_macro, specialization)]
|
#![feature(proc_macro, specialization, const_fn)]
|
||||||
|
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
```
|
```
|
||||||
|
|
|
@ -106,9 +106,9 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
impl _pyo3::ToPyPointer for #cls {
|
impl _pyo3::ToPyPointer for #cls {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
|
||||||
unsafe {
|
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 NAME: &'static str = #cls_name;
|
||||||
const DESCRIPTION: &'static str = #doc;
|
const DESCRIPTION: &'static str = #doc;
|
||||||
|
|
||||||
#[inline]
|
const SIZE: usize = Self::OFFSET as usize + std::mem::size_of::<#cls>();
|
||||||
fn size() -> usize {
|
const OFFSET: isize = {
|
||||||
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();
|
|
||||||
|
|
||||||
// round base_size up to next multiple of align
|
// 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]
|
#[inline]
|
||||||
unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
|
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;
|
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
||||||
|
|
||||||
if checked {
|
if checked {
|
||||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
let ptr = (ptr as *mut u8)
|
||||||
let ptr = (ptr as *mut u8).offset(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
|
||||||
|
@ -233,8 +226,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
let ptr = ob.as_ptr();
|
let ptr = ob.as_ptr();
|
||||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
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)
|
||||||
let ptr = (ptr as *mut u8).offset(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
|
||||||
|
@ -245,15 +238,15 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
|
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)
|
||||||
let ptr = (ob.as_ptr() as *mut u8).offset(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 offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
let ptr = (ob.as_ptr() as *mut u8)
|
||||||
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls;
|
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
|
||||||
&mut *ptr
|
&mut *ptr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,8 +260,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
|
||||||
|
|
||||||
if checked {
|
if checked {
|
||||||
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
|
let ptr = (ptr as *mut u8)
|
||||||
let ptr = (ptr as *mut u8).offset(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
|
||||||
|
@ -281,8 +274,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
|
||||||
let ptr = ob.as_ptr();
|
let ptr = ob.as_ptr();
|
||||||
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
|
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)
|
||||||
let ptr = (ptr as *mut u8).offset(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
|
||||||
|
|
|
@ -81,15 +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 offset = <T as PyTypeInfo>::offset();
|
let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::OFFSET) as *mut T;
|
||||||
let ptr = (obj as *mut u8).offset(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) {
|
||||||
|
|
|
@ -205,17 +205,15 @@ 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 {
|
||||||
let offset = <T as PyTypeInfo>::offset();
|
|
||||||
unsafe {
|
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()
|
ptr.as_ref().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
default fn as_mut(&self, _py: Python) -> &mut T {
|
default fn as_mut(&self, _py: Python) -> &mut T {
|
||||||
let offset = <T as PyTypeInfo>::offset();
|
|
||||||
unsafe {
|
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()
|
ptr.as_mut().unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,15 +138,9 @@ 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 {
|
|
||||||
$crate::std::mem::size_of::<$crate::ffi::PyObject>()
|
|
||||||
}
|
|
||||||
#[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 {
|
||||||
&mut $crate::ffi::$typeobject
|
&mut $crate::ffi::$typeobject
|
||||||
|
|
|
@ -18,16 +18,18 @@ use class::methods::PyMethodDefType;
|
||||||
pub trait PyTypeInfo {
|
pub trait PyTypeInfo {
|
||||||
/// Type of objects to store in PyObject struct
|
/// Type of objects to store in PyObject struct
|
||||||
type Type;
|
type Type;
|
||||||
|
|
||||||
/// Class name
|
/// Class name
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
|
|
||||||
/// Class doc string
|
/// Class doc string
|
||||||
const DESCRIPTION: &'static str = "\0";
|
const DESCRIPTION: &'static str = "\0";
|
||||||
|
|
||||||
/// Size of the PyObject structure
|
/// Size of the rust PyObject structure (PyObject + rust structure)
|
||||||
fn size() -> usize;
|
const SIZE: usize;
|
||||||
|
|
||||||
/// `Type` instance offset inside PyObject structure
|
/// `Type` instance offset inside PyObject structure
|
||||||
fn offset() -> isize;
|
const OFFSET: isize;
|
||||||
|
|
||||||
/// 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;
|
||||||
|
@ -41,16 +43,9 @@ pub trait PyTypeInfo {
|
||||||
impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
|
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;
|
||||||
#[inline]
|
const SIZE: usize = T::SIZE;
|
||||||
default fn size() -> usize {
|
const OFFSET: isize = T::OFFSET;
|
||||||
<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 {
|
||||||
|
@ -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> {
|
default unsafe fn alloc(py: Python, value: T) -> PyResult<*mut ffi::PyObject> {
|
||||||
// TODO: remove this
|
// TODO: remove this
|
||||||
<T as PyTypeObject>::init_type(py);
|
T::init_type(py);
|
||||||
|
|
||||||
let obj = ffi::PyType_GenericAlloc(
|
let obj = ffi::PyType_GenericAlloc(T::type_object(), 0);
|
||||||
<Self as PyTypeInfo>::type_object(), 0);
|
|
||||||
|
|
||||||
let offset = <Self as PyTypeInfo>::offset();
|
let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
|
||||||
let ptr = (obj as *mut u8).offset(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(<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);
|
std::ptr::drop_in_place(ptr);
|
||||||
|
|
||||||
let ty = ffi::Py_TYPE(obj);
|
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_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;
|
||||||
|
|
||||||
// GC support
|
// GC support
|
||||||
<T as class::gc::PyGCProtocolImpl>::update_type_object(type_object);
|
<T as class::gc::PyGCProtocolImpl>::update_type_object(type_object);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
#![feature(proc_macro, specialization)]
|
#![feature(proc_macro, specialization, const_fn)]
|
||||||
|
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(proc_macro, specialization)]
|
#![feature(proc_macro, specialization, const_fn)]
|
||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(proc_macro, specialization)]
|
#![feature(proc_macro, specialization, const_fn)]
|
||||||
#![allow(dead_code, unused_variables)]
|
#![allow(dead_code, unused_variables)]
|
||||||
|
|
||||||
extern crate pyo3;
|
extern crate pyo3;
|
||||||
|
|
Loading…
Reference in New Issue