add ptr support to class
This commit is contained in:
parent
4cdb77335e
commit
6834a18a5b
|
@ -17,6 +17,7 @@ mod py_class;
|
|||
mod py_impl;
|
||||
mod py_proto;
|
||||
mod py_method;
|
||||
mod py_ptr;
|
||||
mod defs;
|
||||
mod func;
|
||||
mod method;
|
||||
|
@ -42,7 +43,6 @@ pub fn proto(_: TokenStream, input: TokenStream) -> TokenStream {
|
|||
TokenStream::from_str(s.as_str()).unwrap()
|
||||
}
|
||||
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn class(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
// Construct a string representation of the type definition
|
||||
|
@ -104,3 +104,24 @@ pub fn args(_: TokenStream, input: TokenStream) -> TokenStream {
|
|||
pub fn defaults(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||
input
|
||||
}
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn ptr(attr: TokenStream, input: TokenStream) -> TokenStream {
|
||||
// Construct a string representation of the type definition
|
||||
let source = input.to_string();
|
||||
|
||||
let cls = syn::Ident::from(&attr.to_string()[1..attr.to_string().len()-1]);
|
||||
|
||||
// Parse the string representation into a syntax tree
|
||||
let mut ast = syn::parse_derive_input(&source).unwrap();
|
||||
|
||||
// Build the output
|
||||
let expanded = py_ptr::build_ptr(cls, &mut ast);
|
||||
|
||||
// Return the generated impl as a TokenStream
|
||||
let mut tokens = Tokens::new();
|
||||
ast.to_tokens(&mut tokens);
|
||||
let s = String::from(tokens.as_str()) + expanded.as_str();
|
||||
|
||||
TokenStream::from_str(s.as_str()).unwrap()
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ pub fn build_py_class(ast: &mut syn::DeriveInput) -> Tokens {
|
|||
_ => (),
|
||||
}
|
||||
attrs.push(attr.clone());
|
||||
println!("FIELD: {:?}", attr);
|
||||
}
|
||||
field.attrs = attrs;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) 2017-present PyO3 Project and Contributors
|
||||
|
||||
use syn;
|
||||
use quote::Tokens;
|
||||
|
||||
pub fn build_ptr(cls: syn::Ident, ast: &mut syn::DeriveInput) -> Tokens {
|
||||
let ptr = &ast.ident;
|
||||
let dummy_const = syn::Ident::new(format!("_IMPL_PYO3_CLS_PTR_{}", ast.ident));
|
||||
|
||||
quote! {
|
||||
#[feature(specialization)]
|
||||
#[allow(non_upper_case_globals, unused_attributes,
|
||||
unused_qualifications, unused_variables, non_camel_case_types)]
|
||||
const #dummy_const: () = {
|
||||
use std;
|
||||
extern crate pyo3 as _pyo3;
|
||||
|
||||
// thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl Send for #ptr {}
|
||||
unsafe impl Sync for #ptr {}
|
||||
|
||||
impl _pyo3::python::ParkRef for #cls {
|
||||
type Target = #ptr;
|
||||
|
||||
fn park(&self) -> #ptr {
|
||||
let token = _pyo3::PythonObjectWithToken::token(self);
|
||||
let ptr = self.clone_ref(token).into_ptr();
|
||||
|
||||
#ptr(unsafe{_pyo3::PyPtr::from_owned_ptr(ptr)})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> _pyo3::python::Unpark<'p> for #ptr {
|
||||
type Target = Py<'p, #cls>;
|
||||
|
||||
fn unpark(self, _py: Python<'p>) -> Py<'p, #cls> {
|
||||
unsafe {std::mem::transmute(self)}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for #ptr {
|
||||
type Target = _pyo3::pointers::PyPtr;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl _pyo3::IntoPyObject for #ptr {
|
||||
|
||||
fn into_object(self, _py: Python) -> _pyo3::PyObjectPtr {
|
||||
unsafe {std::mem::transmute(self)}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -42,3 +42,15 @@ pub enum CompareOp {
|
|||
}
|
||||
|
||||
pub trait PyCustomObject : PyTypeInfo + Sized {}
|
||||
|
||||
|
||||
impl<T> ::python::PyClone for T where T: ::PythonObjectWithToken + PyTypeInfo {
|
||||
#[inline]
|
||||
fn clone_ref<'p>(&self, py: ::Python<'p>) -> ::PyObject<'p> {
|
||||
unsafe {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
let ptr = (self as *const _ as *mut u8).offset(-offset) as *mut ffi::PyObject;
|
||||
::PyObject::from_borrowed_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ pub mod ffi;
|
|||
pub use ffi::{Py_ssize_t, Py_hash_t};
|
||||
|
||||
pub mod pointers;
|
||||
pub use pointers::{Py, PyPtr, PPyPtr};
|
||||
pub use pointers::{Py, PyPtr};
|
||||
|
||||
mod ppptr;
|
||||
pub use ppptr::{pyptr};
|
||||
|
@ -77,8 +77,8 @@ pub use err::{PyErr, PyResult, PyDowncastError};
|
|||
pub use objects::*;
|
||||
pub use objectprotocol::ObjectProtocol;
|
||||
pub use python::{Python, ToPythonPointer, IntoPythonPointer,
|
||||
Park, Unpark,
|
||||
PyDowncastFrom, PyDowncastInto};
|
||||
Park, ParkRef,
|
||||
PyClone, PyDowncastFrom, PyDowncastInto};
|
||||
pub use pythonrun::{GILGuard, GILProtected, prepare_freethreaded_python};
|
||||
pub use conversion::{FromPyObject, RefFromPyObject, ToPyObject, IntoPyObject, ToPyTuple};
|
||||
pub use class::{CompareOp};
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::cmp::Ordering;
|
|||
use ffi;
|
||||
use libc;
|
||||
use pyptr;
|
||||
use pointers::{Py, PyPtr, PPyPtr};
|
||||
use pointers::{Py, PyPtr};
|
||||
use python::{Python, PyDowncastInto, ToPythonPointer};
|
||||
use objects::{PyObject, PyDict, PyString, PyIterator};
|
||||
use token::PythonObjectWithGilToken;
|
||||
|
@ -402,32 +402,7 @@ impl<'p, T> fmt::Display for Py<'p, T> where T: ObjectProtocol<'p> + PyTypeInfo
|
|||
}
|
||||
}
|
||||
|
||||
impl<'p, T> fmt::Debug for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
||||
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
// TODO: we shouldn't use fmt::Error when repr() fails
|
||||
let r = self.as_object(py);
|
||||
let repr_obj = try!(r.repr().map_err(|_| fmt::Error));
|
||||
f.write_str(&repr_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> fmt::Display for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
||||
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
||||
// TODO: we shouldn't use fmt::Error when repr() fails
|
||||
let r = self.as_object(py);
|
||||
let repr_obj = try!(r.str().map_err(|_| fmt::Error));
|
||||
f.write_str(&repr_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl fmt::Debug for PPyPtr {
|
||||
impl fmt::Debug for PyPtr {
|
||||
fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
@ -439,7 +414,7 @@ impl fmt::Debug for PPyPtr {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PPyPtr {
|
||||
impl fmt::Display for PyPtr {
|
||||
default fn fmt(&self, f : &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use pyptr;
|
||||
use ffi;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use objects::PyObject;
|
||||
use native::PyNativeObject;
|
||||
|
@ -8,7 +8,7 @@ use conversion::ToPyObject;
|
|||
|
||||
/// Represents a Python `bool`.
|
||||
pub struct PyBool<'p>(pyptr<'p>);
|
||||
pub struct PyBoolPtr(PPyPtr);
|
||||
pub struct PyBoolPtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PyBool, PyBool_Check, PyBool_Type, PyBoolPtr);
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ use python::{Python, ToPythonPointer};
|
|||
use objects::PyObject;
|
||||
use err::{PyResult, PyErr};
|
||||
use ppptr::pyptr;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use token::PythonObjectWithGilToken;
|
||||
|
||||
|
||||
/// Represents a Python bytearray.
|
||||
pub struct PyByteArray<'p>(pyptr<'p>);
|
||||
pub struct PyByteArrayPtr(PPyPtr);
|
||||
pub struct PyByteArrayPtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PyByteArray, PyByteArray_Check, PyByteArray_Type, PyByteArrayPtr);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::{mem, collections, hash, cmp};
|
|||
|
||||
use ffi;
|
||||
use pyptr;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPythonPointer, PyDowncastInto};
|
||||
use conversion::{ToPyObject};
|
||||
use objects::{PyObject, PyList};
|
||||
|
@ -16,7 +16,7 @@ use native::PyNativeObject;
|
|||
|
||||
/// Represents a Python `dict`.
|
||||
pub struct PyDict<'p>(pyptr<'p>);
|
||||
pub struct PyDictPtr(PPyPtr);
|
||||
pub struct PyDictPtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PyDict, PyDict_Check, PyDict_Type, PyDictPtr);
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use ::pyptr;
|
||||
use err::{self, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer, Park};
|
||||
use objects::PyObject;
|
||||
use token::PythonObjectWithGilToken;
|
||||
|
@ -13,7 +13,7 @@ use conversion::{ToPyObject, IntoPyObject};
|
|||
|
||||
/// Represents a Python `list`.
|
||||
pub struct PyList<'p>(pyptr<'p>);
|
||||
pub struct PyListPtr(PPyPtr);
|
||||
pub struct PyListPtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PyList, PyList_Check, PyList_Type, PyListPtr);
|
||||
|
||||
|
@ -142,7 +142,7 @@ impl <T> IntoPyObject for Vec<T> where T: IntoPyObject {
|
|||
mod test {
|
||||
use python::{Python, PyDowncastInto};
|
||||
use native::PyNativeObject;
|
||||
use conversion::{ToPyObject, IntoPyObject};
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyList;
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -55,6 +55,10 @@ macro_rules! pyobject_nativetype(
|
|||
}
|
||||
}
|
||||
|
||||
// thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl Send for $ptr {}
|
||||
unsafe impl Sync for $ptr {}
|
||||
|
||||
impl<'p> $crate::python::Unpark<'p> for $ptr {
|
||||
type Target = $name<'p>;
|
||||
|
||||
|
@ -64,7 +68,7 @@ macro_rules! pyobject_nativetype(
|
|||
}
|
||||
|
||||
impl $crate::std::ops::Deref for $ptr {
|
||||
type Target = PPyPtr;
|
||||
type Target = PyPtr;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
|
@ -105,7 +109,7 @@ macro_rules! pyobject_nativetype(
|
|||
unsafe{
|
||||
let ptr = ob.into_ptr();
|
||||
if ffi::$checkfunction(ptr) != 0 {
|
||||
Ok($ptr($crate::PPyPtr::from_owned_ptr(ptr)))
|
||||
Ok($ptr($crate::PyPtr::from_owned_ptr(ptr)))
|
||||
} else {
|
||||
$crate::ffi::Py_DECREF(ptr);
|
||||
Err($crate::PyDowncastError(py, None))
|
||||
|
@ -118,7 +122,7 @@ macro_rules! pyobject_nativetype(
|
|||
{
|
||||
unsafe{
|
||||
if ffi::$checkfunction(ptr) != 0 {
|
||||
Ok($ptr($crate::PPyPtr::from_owned_ptr(ptr)))
|
||||
Ok($ptr($crate::PyPtr::from_owned_ptr(ptr)))
|
||||
} else {
|
||||
$crate::ffi::Py_DECREF(ptr);
|
||||
Err($crate::PyDowncastError(py, None))
|
||||
|
@ -166,9 +170,6 @@ macro_rules! pyobject_nativetype(
|
|||
impl<'p> $crate::native::PyBaseObject for $name<'p> {}
|
||||
|
||||
impl<'p> $crate::native::PyNativeObject<'p> for $name<'p> {
|
||||
//fn park(self) -> $crate::PyObjectPtr {
|
||||
// unsafe { $crate::std::mem::transmute(self) }
|
||||
//}
|
||||
fn as_object(self) -> $crate::PyObject<'p> {
|
||||
unsafe {
|
||||
$crate::ffi::Py_INCREF(self.as_ptr());
|
||||
|
@ -189,6 +190,12 @@ macro_rules! pyobject_nativetype(
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> $crate::PyClone for $name<'a> {
|
||||
fn clone_ref<'p>(&self, py: $crate::Python<'p>) -> $crate::PyObject<'p> {
|
||||
$crate::PyObject::from_borrowed_ptr(py, self.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> $crate::python::PyDowncastFrom<'p> for $name<'p>
|
||||
{
|
||||
fn downcast_from(py: &'p $crate::PyObject<'p>)
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::ffi::{CStr, CString};
|
|||
|
||||
use ::pyptr;
|
||||
use conversion::{ToPyObject, ToPyTuple};
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use token::PythonObjectWithGilToken;
|
||||
use objects::{PyObject, PyDict, PyType, exc};
|
||||
|
@ -19,7 +19,7 @@ use err::{PyResult, PyErr};
|
|||
|
||||
/// Represents a Python module object.
|
||||
pub struct PyModule<'p>(pyptr<'p>);
|
||||
pub struct PyModulePtr(PPyPtr);
|
||||
pub struct PyModulePtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PyModule, PyModule_Check, PyModule_Type, PyModulePtr);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use pyptr;
|
|||
use objects::exc;
|
||||
use objects::PyObject;
|
||||
use token::PythonObjectWithGilToken;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use err::{PyResult, PyErr};
|
||||
use native::PyNativeObject;
|
||||
|
@ -25,7 +25,7 @@ use conversion::{ToPyObject, FromPyObject};
|
|||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with the primitive Rust integer types.
|
||||
pub struct PyLong<'p>(pyptr<'p>);
|
||||
pub struct PyLongPtr(PPyPtr);
|
||||
pub struct PyLongPtr(PyPtr);
|
||||
pyobject_nativetype!(PyLong, PyLong_Check, PyLong_Type, PyLongPtr);
|
||||
|
||||
/// Represents a Python `float` object.
|
||||
|
@ -35,7 +35,7 @@ pyobject_nativetype!(PyLong, PyLong_Check, PyLong_Type, PyLongPtr);
|
|||
/// and [extract](struct.PyObject.html#method.extract)
|
||||
/// with `f32`/`f64`.
|
||||
pub struct PyFloat<'p>(pyptr<'p>);
|
||||
pub struct PyFloatPtr(PPyPtr);
|
||||
pub struct PyFloatPtr(PyPtr);
|
||||
pyobject_nativetype!(PyFloat, PyFloat_Check, PyFloat_Type, PyFloatPtr);
|
||||
|
||||
|
||||
|
|
|
@ -4,14 +4,14 @@ use std;
|
|||
|
||||
use ::pyptr;
|
||||
use ffi;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use python::{Python, ToPythonPointer};
|
||||
|
||||
|
||||
pub struct PyObject<'p>(pyptr<'p>);
|
||||
|
||||
pub struct PyObjectPtr(PPyPtr);
|
||||
pub struct PyObjectPtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PyObject, PyObject_Check, PyBaseObject_Type, PyObjectPtr);
|
||||
|
||||
|
@ -117,7 +117,7 @@ impl PyObjectPtr {
|
|||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(ptr: *mut ffi::PyObject) -> PyObjectPtr {
|
||||
PyObjectPtr(PPyPtr::from_owned_ptr(ptr))
|
||||
PyObjectPtr(PyPtr::from_owned_ptr(ptr))
|
||||
}
|
||||
|
||||
/// Creates a `PyObjectPtr` instance for the given FFI pointer.
|
||||
|
@ -128,7 +128,7 @@ impl PyObjectPtr {
|
|||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObjectPtr(unsafe{PPyPtr::from_owned_ptr(ptr)}))
|
||||
Some(PyObjectPtr(unsafe{PyPtr::from_owned_ptr(ptr)}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,7 +141,7 @@ impl PyObjectPtr {
|
|||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(PyObjectPtr(unsafe{PPyPtr::from_owned_ptr(ptr)}))
|
||||
Ok(PyObjectPtr(unsafe{PyPtr::from_owned_ptr(ptr)}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ impl PyObjectPtr {
|
|||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
PyObjectPtr(PPyPtr::from_owned_ptr(ptr))
|
||||
PyObjectPtr(PyPtr::from_owned_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ impl PyObjectPtr {
|
|||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> PyObjectPtr {
|
||||
PyObjectPtr(PPyPtr::from_borrowed_ptr(ptr))
|
||||
PyObjectPtr(PyPtr::from_borrowed_ptr(ptr))
|
||||
}
|
||||
|
||||
/// Creates a `PyObjectPtr` instance for the given Python FFI pointer.
|
||||
|
@ -173,7 +173,7 @@ impl PyObjectPtr {
|
|||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyObjectPtr(unsafe{PPyPtr::from_borrowed_ptr(ptr)}))
|
||||
Some(PyObjectPtr(unsafe{PyPtr::from_borrowed_ptr(ptr)}))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +186,7 @@ impl PyObjectPtr {
|
|||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
PyObjectPtr(PPyPtr::from_borrowed_ptr(ptr))
|
||||
PyObjectPtr(PyPtr::from_borrowed_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{hash, collections};
|
|||
use ffi;
|
||||
use pyptr;
|
||||
use python::{Python, ToPythonPointer};
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use conversion::ToPyObject;
|
||||
use objects::PyObject;
|
||||
use err::{self, PyResult, PyErr};
|
||||
|
@ -15,11 +15,11 @@ use token::{PythonObjectWithGilToken};
|
|||
|
||||
/// Represents a Python `set`
|
||||
pub struct PySet<'p>(pyptr<'p>);
|
||||
pub struct PySetPtr(PPyPtr);
|
||||
pub struct PySetPtr(PyPtr);
|
||||
|
||||
/// Represents a Python `frozenset`
|
||||
pub struct PyFrozenSet<'p>(pyptr<'p>);
|
||||
pub struct PyFrozenSetPtr(PPyPtr);
|
||||
pub struct PyFrozenSetPtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PySet, PySet_Check, PySet_Type, PySetPtr);
|
||||
pyobject_nativetype!(PyFrozenSet, PyFrozenSet_Check, PyFrozenSet_Type, PyFrozenSetPtr);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
use std::os::raw::c_long;
|
||||
|
||||
use ::pyptr;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use err::{PyErr, PyResult};
|
||||
use ffi::{self, Py_ssize_t};
|
||||
|
@ -15,7 +15,7 @@ use token::PythonObjectWithGilToken;
|
|||
/// Represents a Python `slice`. Only `c_long` indeces supprted
|
||||
/// at the moment by PySlice object.
|
||||
pub struct PySlice<'p>(pyptr<'p>);
|
||||
pub struct PySlicePtr(PPyPtr);
|
||||
pub struct PySlicePtr(PyPtr);
|
||||
|
||||
pyobject_nativetype!(PySlice, PySlice_Check, PySlice_Type, PySlicePtr);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ use std::os::raw::c_char;
|
|||
|
||||
use ffi;
|
||||
use pyptr;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use super::{exc, PyObject};
|
||||
use token::PythonObjectWithGilToken;
|
||||
|
@ -20,12 +20,12 @@ use conversion::{ToPyObject, RefFromPyObject};
|
|||
|
||||
/// Represents a Python string.
|
||||
pub struct PyString<'p>(pyptr<'p>);
|
||||
pub struct PyStringPtr(PPyPtr);
|
||||
pub struct PyStringPtr(PyPtr);
|
||||
pyobject_nativetype!(PyString, PyUnicode_Check, PyUnicode_Type, PyStringPtr);
|
||||
|
||||
/// Represents a Python byte string.
|
||||
pub struct PyBytes<'p>(pyptr<'p>);
|
||||
pub struct PyBytesPtr(PPyPtr);
|
||||
pub struct PyBytesPtr(PyPtr);
|
||||
pyobject_nativetype!(PyBytes, PyBytes_Check, PyBytes_Type, PyBytesPtr);
|
||||
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::slice;
|
|||
use pyptr;
|
||||
use ffi::{self, Py_ssize_t};
|
||||
use err::{PyErr, PyResult};
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPythonPointer, IntoPythonPointer};
|
||||
use conversion::{FromPyObject, ToPyObject, ToPyTuple, IntoPyObject};
|
||||
use objects::PyObject;
|
||||
|
@ -17,7 +17,7 @@ use super::exc;
|
|||
|
||||
/// Represents a Python tuple object.
|
||||
pub struct PyTuple<'p>(pyptr<'p>);
|
||||
pub struct PyTuplePtr(PPyPtr);
|
||||
pub struct PyTuplePtr(PyPtr);
|
||||
pyobject_nativetype!(PyTuple, PyTuple_Check, PyTuple_Type, PyTuplePtr);
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use std::borrow::Cow;
|
|||
use ::pyptr;
|
||||
use ffi;
|
||||
use token::PythonObjectWithGilToken;
|
||||
use pointers::PPyPtr;
|
||||
use pointers::PyPtr;
|
||||
use python::{Python, ToPythonPointer};
|
||||
use conversion::ToPyTuple;
|
||||
use objects::{PyObject, PyDict};
|
||||
|
@ -16,7 +16,7 @@ use err::{PyErr, PyResult};
|
|||
|
||||
/// Represents a reference to a Python type object.
|
||||
pub struct PyType<'p>(pyptr<'p>);
|
||||
pub struct PyTypePtr(PPyPtr);
|
||||
pub struct PyTypePtr(PyPtr);
|
||||
pyobject_nativetype!(PyType, PyType_Check, PyType_Type, PyTypePtr);
|
||||
|
||||
|
||||
|
@ -83,7 +83,7 @@ impl PyTypePtr {
|
|||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(ptr: *mut ffi::PyObject) -> PyTypePtr {
|
||||
PyTypePtr(PPyPtr::from_owned_ptr(ptr))
|
||||
PyTypePtr(PyPtr::from_owned_ptr(ptr))
|
||||
}
|
||||
|
||||
/// Retrieves the owned PyTypePtr instance for the given FFI pointer.
|
||||
|
@ -95,7 +95,7 @@ impl PyTypePtr {
|
|||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(PyTypePtr(PPyPtr::from_owned_ptr(ptr)))
|
||||
Ok(PyTypePtr(PyPtr::from_owned_ptr(ptr)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,6 @@ impl PyTypePtr {
|
|||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> PyTypePtr {
|
||||
PyTypePtr(PPyPtr::from_owned_ptr(ptr))
|
||||
PyTypePtr(PyPtr::from_owned_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
|
180
src/pointers.rs
180
src/pointers.rs
|
@ -15,31 +15,31 @@ use typeob::{PyTypeInfo, PyObjectAlloc};
|
|||
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
pub struct PPyPtr(*mut ffi::PyObject);
|
||||
pub struct PyPtr(*mut ffi::PyObject);
|
||||
|
||||
// `PPyPtr` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl Send for PPyPtr {}
|
||||
unsafe impl Sync for PPyPtr {}
|
||||
// `PyPtr` is thread-safe, because any python related operations require a Python<'p> token.
|
||||
unsafe impl Send for PyPtr {}
|
||||
unsafe impl Sync for PyPtr {}
|
||||
|
||||
|
||||
impl PPyPtr {
|
||||
impl PyPtr {
|
||||
/// Creates a `PyObjectPtr` instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the `PyObjectPtr`.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(ptr: *mut ffi::PyObject) -> PPyPtr {
|
||||
pub unsafe fn from_owned_ptr(ptr: *mut ffi::PyObject) -> PyPtr {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
PPyPtr(ptr)
|
||||
PyPtr(ptr)
|
||||
}
|
||||
|
||||
/// Creates a `PyObjectPtr` instance for the given Python FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> PPyPtr {
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> PyPtr {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
ffi::Py_INCREF(ptr);
|
||||
PPyPtr::from_owned_ptr(ptr)
|
||||
PyPtr::from_owned_ptr(ptr)
|
||||
}
|
||||
|
||||
/// Gets the reference count of the PyObject pointer.
|
||||
|
@ -54,17 +54,24 @@ impl PPyPtr {
|
|||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts `PyObjectPtr` instance -> PyObject<'p>
|
||||
/// Converts `PyPtr` instance -> PyObject<'p>
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
pub fn into_object<'p>(self, _py: Python<'p>) -> PyObject<'p> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts `PyPtr` instance -> PyObjectPtr
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
pub fn into_object_ptr(self) -> PyObjectPtr {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Clone self, Calls Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub fn clone_ref(&self, _py: Python) -> PPyPtr {
|
||||
unsafe { PPyPtr::from_borrowed_ptr(self.0) }
|
||||
pub fn clone_ref(&self, _py: Python) -> PyPtr {
|
||||
unsafe { PyPtr::from_borrowed_ptr(self.0) }
|
||||
}
|
||||
|
||||
/// Casts the `PyObjectPtr` imstance to a concrete Python object type.
|
||||
|
@ -77,7 +84,7 @@ impl PPyPtr {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToPythonPointer for PPyPtr {
|
||||
impl ToPythonPointer for PyPtr {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
|
@ -85,7 +92,7 @@ impl ToPythonPointer for PPyPtr {
|
|||
}
|
||||
}
|
||||
|
||||
impl IntoPythonPointer for PPyPtr {
|
||||
impl IntoPythonPointer for PyPtr {
|
||||
/// Gets the underlying FFI pointer, returns a owned pointer.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -96,16 +103,16 @@ impl IntoPythonPointer for PPyPtr {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for PPyPtr {
|
||||
impl PartialEq for PyPtr {
|
||||
#[inline]
|
||||
fn eq(&self, o: &PPyPtr) -> bool {
|
||||
fn eq(&self, o: &PyPtr) -> bool {
|
||||
self.0 == o.0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Dropping a `PPyPtr` instance decrements the reference count on the object by 1.
|
||||
impl Drop for PPyPtr {
|
||||
/// Dropping a `PyPtr` instance decrements the reference count on the object by 1.
|
||||
impl Drop for PyPtr {
|
||||
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
|
@ -118,130 +125,6 @@ impl Drop for PPyPtr {
|
|||
}
|
||||
|
||||
|
||||
pub struct PyPtr<T> {
|
||||
inner: *mut ffi::PyObject,
|
||||
_t: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> PyPtr<T> {
|
||||
|
||||
/// Converts PyPtr<T> -> PyObjectPtr
|
||||
/// Consumes `self` without calling `Py_INCREF()`
|
||||
#[inline]
|
||||
pub fn park(self) -> PyObjectPtr {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts PyPtr<T> -> Py<'p, T>
|
||||
/// Consumes `self` without calling `Py_INCREF()`
|
||||
#[inline]
|
||||
pub fn unpark<'p>(self, _py: Python<'p>) -> Py<'p, T> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Returns PyObject reference.
|
||||
#[inline]
|
||||
pub fn as_object<'p>(&self, _py: Python<'p>) -> &PyObject<'p> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts PyPtr<T> -> PyObject<'p>
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
pub fn into_object<'p>(self, _py: Python<'p>) -> PyObject<'p> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clone_ref(&self, _py: Python) -> PyPtr<T> {
|
||||
unsafe {
|
||||
ffi::Py_INCREF(self.inner);
|
||||
PyPtr {inner: self.inner, _t: PhantomData}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PyPtr<T> where T: PyTypeInfo
|
||||
{
|
||||
#[inline]
|
||||
pub fn as_ref(&self, _py: Python) -> &T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
let ptr = (self.inner as *mut u8).offset(offset) as *mut T;
|
||||
ptr.as_ref().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut(&self, _py: Python) -> &mut T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
unsafe {
|
||||
let ptr = (self.inner as *mut u8).offset(offset) as *mut T;
|
||||
ptr.as_mut().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToPythonPointer for PyPtr<T> {
|
||||
/// Gets the underlying FFI pointer, returns a borrowed pointer.
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut ffi::PyObject {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoPythonPointer for PyPtr<T> {
|
||||
/// Gets the underlying FFI pointer.
|
||||
/// Consumes `self` without calling `Py_DECREF()`, thus returning an owned pointer.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
fn into_ptr(self) -> *mut ffi::PyObject {
|
||||
let ptr = self.inner;
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToPyObject for PyPtr<T> {
|
||||
|
||||
#[inline]
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyObject<'p> {
|
||||
PyObject::from_borrowed_ptr(py, self.inner)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn with_borrowed_ptr<F, R>(&self, _py: Python, f: F) -> R
|
||||
where F: FnOnce(*mut ffi::PyObject) -> R
|
||||
{
|
||||
f(self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> IntoPyObject for PyPtr<T> {
|
||||
|
||||
#[inline]
|
||||
fn into_object<'a>(self, _py: Python) -> ::PyObjectPtr {
|
||||
self.park()
|
||||
}
|
||||
}
|
||||
|
||||
// PyPtr is thread-safe, because all operations on it require a Python<'p> token.
|
||||
unsafe impl<T> Send for PyPtr<T> {}
|
||||
unsafe impl<T> Sync for PyPtr<T> {}
|
||||
|
||||
/// Dropping a `PyPtr` decrements the reference count on the object by 1.
|
||||
impl<T> Drop for PyPtr<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
println!("drop PyPtr: {:?} {}", self.inner, ffi::Py_REFCNT(self.inner));
|
||||
}
|
||||
|
||||
let _gil_guard = Python::acquire_gil();
|
||||
unsafe { ffi::Py_DECREF(self.inner); }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct Py<'p, T> {
|
||||
pub inner: *mut ffi::PyObject,
|
||||
_t: PhantomData<T>,
|
||||
|
@ -269,12 +152,6 @@ impl<'p, T> Py<'p, T>
|
|||
Py {inner: ptr, _t: PhantomData, py: py}
|
||||
}
|
||||
|
||||
/// Convert tp `PyPtr<T>` pointer
|
||||
#[inline]
|
||||
pub fn park(self) -> PyPtr<T> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Returns owned PyObject<'p> reference
|
||||
#[inline]
|
||||
pub fn as_object(&self) -> &'p PyObject<'p> {
|
||||
|
@ -433,10 +310,3 @@ impl<'p, T> PartialEq for Py<'p, T> {
|
|||
self.as_ptr() == o.as_ptr()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PartialEq for PyPtr<T> {
|
||||
#[inline]
|
||||
fn eq(&self, o: &PyPtr<T>) -> bool {
|
||||
self.as_ptr() == o.as_ptr()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,15 +53,28 @@ pub trait PyDowncastInto<'p> : Sized {
|
|||
|
||||
pub trait Park : Sized {
|
||||
type Target;
|
||||
|
||||
fn park(self) -> Self::Target;
|
||||
}
|
||||
|
||||
pub trait ParkRef : Sized {
|
||||
type Target;
|
||||
|
||||
fn park(&self) -> Self::Target;
|
||||
}
|
||||
|
||||
pub trait Unpark<'p> : Sized {
|
||||
type Target;
|
||||
|
||||
fn unpark(self, py: Python<'p>) -> Self::Target;
|
||||
}
|
||||
|
||||
|
||||
pub trait PyClone {
|
||||
|
||||
fn clone_ref<'p>(&self, py: Python<'p>) -> PyObject<'p>;
|
||||
}
|
||||
|
||||
/// This trait allows retrieving the underlying FFI pointer from Python objects.
|
||||
pub trait ToPythonPointer {
|
||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
||||
|
|
|
@ -68,12 +68,18 @@ fn empty_class_in_module() {
|
|||
}
|
||||
|
||||
#[py::class]
|
||||
struct EmptyClassWithNew {token: PythonToken<EmptyClassWithNew> }
|
||||
struct EmptyClassWithNew {
|
||||
#[token]
|
||||
token: PythonToken<EmptyClassWithNew>
|
||||
}
|
||||
|
||||
#[py::ptr(EmptyClassWithNew)]
|
||||
struct EmptyClassWithNewPtr(PyPtr);
|
||||
|
||||
#[py::methods]
|
||||
impl EmptyClassWithNew {
|
||||
#[__new__]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<PyPtr<EmptyClassWithNew>> {
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<EmptyClassWithNewPtr> {
|
||||
Ok(py.with_token(|t| EmptyClassWithNew{token: t}).park())
|
||||
}
|
||||
}
|
||||
|
@ -92,10 +98,14 @@ struct NewWithOneArg {
|
|||
#[token]
|
||||
token: PythonToken<NewWithOneArg>
|
||||
}
|
||||
|
||||
#[py::ptr(NewWithOneArg)]
|
||||
struct NewWithOneArgPtr(PyPtr);
|
||||
|
||||
#[py::methods]
|
||||
impl NewWithOneArg {
|
||||
#[new]
|
||||
fn __new__(_cls: &PyType, py: Python, arg: i32) -> PyResult<PyPtr<NewWithOneArg>> {
|
||||
fn __new__(_cls: &PyType, py: Python, arg: i32) -> PyResult<NewWithOneArgPtr> {
|
||||
Ok(py.with_token(|t| NewWithOneArg{_data: arg, token: t}).park())
|
||||
}
|
||||
}
|
||||
|
@ -114,14 +124,18 @@ fn new_with_one_arg() {
|
|||
struct NewWithTwoArgs {
|
||||
_data1: i32,
|
||||
_data2: i32,
|
||||
|
||||
#[token]
|
||||
token: PythonToken<NewWithTwoArgs>
|
||||
}
|
||||
|
||||
#[py::ptr(NewWithTwoArgs)]
|
||||
struct NewWithTwoArgsPtr(PyPtr);
|
||||
|
||||
#[py::methods]
|
||||
impl NewWithTwoArgs {
|
||||
#[new]
|
||||
fn __new__(_cls: &PyType, py: Python, arg1: i32, arg2: i32)
|
||||
-> PyResult<PyPtr<NewWithTwoArgs>> {
|
||||
fn __new__(_cls: &PyType, py: Python, arg1: i32, arg2: i32) -> PyResult<NewWithTwoArgsPtr> {
|
||||
Ok(py.with_token(|t| NewWithTwoArgs{_data1: arg1, _data2: arg2, token: t}).park())
|
||||
}
|
||||
}
|
||||
|
@ -268,12 +282,18 @@ fn class_method() {
|
|||
}*/
|
||||
|
||||
#[py::class]
|
||||
struct StaticMethod {token: PythonToken<StaticMethod>}
|
||||
struct StaticMethod {
|
||||
#[token]
|
||||
token: PythonToken<StaticMethod>
|
||||
}
|
||||
|
||||
#[py::ptr(StaticMethod)]
|
||||
struct StaticMethodPtr(PyPtr);
|
||||
|
||||
#[py::methods]
|
||||
impl StaticMethod {
|
||||
#[new]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<PyPtr<StaticMethod>> {
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<StaticMethodPtr> {
|
||||
Ok(py.with_token(|t| StaticMethod{token: t}).park())
|
||||
}
|
||||
|
||||
|
@ -318,9 +338,13 @@ impl StaticMethod {
|
|||
struct GCIntegration {
|
||||
self_ref: RefCell<PyObjectPtr>,
|
||||
dropped: TestDropCall,
|
||||
#[token]
|
||||
token: PythonToken<GCIntegration>,
|
||||
}
|
||||
|
||||
#[py::ptr(GCIntegration)]
|
||||
struct GCIntegrationPtr(PyPtr);
|
||||
|
||||
#[py::proto]
|
||||
impl PyGCProtocol for GCIntegration {
|
||||
fn __traverse__(&self, py: Python, visit: PyVisit) -> Result<(), PyTraverseError> {
|
||||
|
@ -343,7 +367,7 @@ fn gc_integration() {
|
|||
dropped: TestDropCall { drop_called: drop_called.clone() },
|
||||
token: t});
|
||||
|
||||
*inst.self_ref.borrow_mut() = inst.clone().park().park();
|
||||
*inst.self_ref.borrow_mut() = inst.clone_ref(py).park();
|
||||
drop(inst);
|
||||
|
||||
py.run("import gc; gc.collect()", None, None).unwrap();
|
||||
|
|
Loading…
Reference in New Issue