simplify Py and PyPtr objects
This commit is contained in:
parent
3040ac12b9
commit
5d25c7deea
|
@ -1,9 +1,10 @@
|
|||
use ffi;
|
||||
use err::PyResult;
|
||||
use pointers::pptr;
|
||||
use python::{Python, ToPythonPointer};
|
||||
use python::{Python, ToPythonPointer, PyDowncastFrom};
|
||||
use objects::{PyObject, PyTuple};
|
||||
use native::PyNativeObject;
|
||||
use typeob::PyTypeInfo;
|
||||
|
||||
|
||||
/// Conversion trait that allows various objects to be converted into PyObject
|
||||
|
@ -147,7 +148,6 @@ impl<T> IntoPyObject for Option<T> where T: IntoPyObject {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// `()` is converted to Python `None`.
|
||||
impl ToPyObject for () {
|
||||
fn to_object<'p>(&self, py: Python<'p>) -> PyObject<'p> {
|
||||
|
@ -155,6 +155,16 @@ impl ToPyObject for () {
|
|||
}
|
||||
}
|
||||
|
||||
/// Extract reference to instance from PyObject
|
||||
impl<'source, T> ::FromPyObject<'source> for &'source T
|
||||
where T: PyTypeInfo + PyDowncastFrom<'source>
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(py: &'source PyObject<'source>) -> PyResult<&'source T>
|
||||
{
|
||||
Ok(py.cast_as()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl <'source, T> FromPyObject<'source> for Option<T> where T: FromPyObject<'source> {
|
||||
fn extract(obj: &'source PyObject) -> PyResult<Self>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
use std::ptr;
|
||||
|
||||
use ffi;
|
||||
use pointers::Py;
|
||||
use python::Python;
|
||||
use objects::PyObject;
|
||||
|
||||
|
@ -140,6 +139,6 @@ macro_rules! py_fn_impl {
|
|||
|
||||
#[allow(dead_code)]
|
||||
pub unsafe fn py_fn_impl<'p>(py: Python<'p>,
|
||||
method_def: *mut ffi::PyMethodDef) -> Py<'p, PyObject> {
|
||||
Py::from_owned_ptr_or_panic(py, ffi::PyCFunction_New(method_def, ptr::null_mut()))
|
||||
method_def: *mut ffi::PyMethodDef) -> PyObject<'p> {
|
||||
PyObject::from_owned_ptr_or_panic(py, ffi::PyCFunction_New(method_def, ptr::null_mut()))
|
||||
}
|
||||
|
|
|
@ -216,7 +216,7 @@ pub unsafe fn py_module_init_impl(
|
|||
return module;
|
||||
}
|
||||
|
||||
let module = match Py::<PyModule>::cast_from_owned_ptr(py, module) {
|
||||
let module = match PyObject::from_owned_ptr(py, module).cast_into::<PyModule>(py) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
PyErr::from(e).restore(py);
|
||||
|
|
|
@ -408,7 +408,7 @@ impl<'p, T> fmt::Debug for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
|||
let py = gil.python();
|
||||
|
||||
// TODO: we shouldn't use fmt::Error when repr() fails
|
||||
let r = self.as_ref(py);
|
||||
let r = self.as_object(py);
|
||||
let repr_obj = try!(r.repr().map_err(|_| fmt::Error));
|
||||
f.write_str(&repr_obj.to_string_lossy())
|
||||
}
|
||||
|
@ -420,8 +420,8 @@ impl<'p, T> fmt::Display for PyPtr<T> where T: ObjectProtocol<'p> + PyTypeInfo {
|
|||
let py = gil.python();
|
||||
|
||||
// TODO: we shouldn't use fmt::Error when repr() fails
|
||||
let r = self.as_ref(py);
|
||||
let repr_obj = try!(r.as_ref().str().map_err(|_| fmt::Error));
|
||||
let r = self.as_object(py);
|
||||
let repr_obj = try!(r.str().map_err(|_| fmt::Error));
|
||||
f.write_str(&repr_obj.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,9 @@ impl<'p> PyDict<'p> {
|
|||
}
|
||||
|
||||
/// Construct a new dict with the given raw pointer
|
||||
pub fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyDict<'p> {
|
||||
unsafe { PyDict(pyptr::from_borrowed_ptr(py, ptr)) }
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
pub unsafe fn from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject) -> PyDict<'p> {
|
||||
PyDict(pyptr::from_borrowed_ptr(py, ptr))
|
||||
}
|
||||
|
||||
/// Return a new dictionary that contains the same key-value pairs as self.
|
||||
|
|
|
@ -9,7 +9,7 @@ use std::{self, mem, ops};
|
|||
use std::ffi::CStr;
|
||||
|
||||
use ffi;
|
||||
use pointers::PyPtr;
|
||||
use pointers::pptr;
|
||||
use python::{Python, ToPythonPointer};
|
||||
use err::PyResult;
|
||||
use native::PyNativeObject;
|
||||
|
@ -86,10 +86,10 @@ exc_type!(UnicodeTranslateError, PyExc_UnicodeTranslateError);
|
|||
impl UnicodeDecodeError {
|
||||
|
||||
pub fn new(py: Python, encoding: &CStr, input: &[u8], range: ops::Range<usize>, reason: &CStr)
|
||||
-> PyResult<PyPtr<UnicodeDecodeError>> {
|
||||
-> PyResult<pptr> {
|
||||
unsafe {
|
||||
let input: &[c_char] = mem::transmute(input);
|
||||
PyPtr::from_owned_ptr_or_err(
|
||||
pptr::from_owned_ptr_or_err(
|
||||
py, ffi::PyUnicodeDecodeError_Create(
|
||||
encoding.as_ptr(),
|
||||
input.as_ptr(),
|
||||
|
@ -101,7 +101,7 @@ impl UnicodeDecodeError {
|
|||
}
|
||||
|
||||
pub fn new_utf8<'p>(py: Python, input: &[u8], err: std::str::Utf8Error)
|
||||
-> PyResult<PyPtr<UnicodeDecodeError>>
|
||||
-> PyResult<pptr>
|
||||
{
|
||||
let pos = err.valid_up_to();
|
||||
UnicodeDecodeError::new(py, cstr!("utf-8"), input, pos .. pos+1, cstr!("invalid utf-8"))
|
||||
|
|
|
@ -55,7 +55,10 @@ macro_rules! pyobject_nativetype(
|
|||
unsafe { $crate::std::mem::transmute(self) }
|
||||
}
|
||||
fn as_object(self) -> $crate::PyObject<'p> {
|
||||
unsafe { $crate::std::mem::transmute(self) }
|
||||
unsafe {
|
||||
$crate::ffi::Py_INCREF(self.as_ptr());
|
||||
$crate::std::mem::transmute(self)
|
||||
}
|
||||
}
|
||||
fn clone_object(&self) -> $name<'p> {
|
||||
use $crate::{ToPythonPointer, PythonObjectWithGilToken};
|
||||
|
|
|
@ -9,7 +9,6 @@ use std::ffi::{CStr, CString};
|
|||
|
||||
use ::pyptr;
|
||||
use conversion::{ToPyObject, ToPyTuple};
|
||||
use pointers::PyPtr;
|
||||
use python::{ToPythonPointer, Python};
|
||||
use token::PythonObjectWithGilToken;
|
||||
use objects::{PyObject, PyDict, PyType, exc};
|
||||
|
@ -46,9 +45,9 @@ impl<'p> PyModule<'p> {
|
|||
|
||||
/// Return the dictionary object that implements module's namespace;
|
||||
/// this object is the same as the `__dict__` attribute of the module object.
|
||||
pub fn dict(&self) -> PyPtr<PyDict> {
|
||||
pub fn dict(&self) -> PyDict<'p> {
|
||||
unsafe {
|
||||
PyPtr::from_borrowed_ptr(ffi::PyModule_GetDict(self.as_ptr()))
|
||||
PyDict::from_borrowed_ptr(self.gil(), ffi::PyModule_GetDict(self.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
417
src/pointers.rs
417
src/pointers.rs
|
@ -196,104 +196,28 @@ impl Drop for pptr {
|
|||
}
|
||||
|
||||
|
||||
|
||||
pub struct PyPtr<T> {
|
||||
inner: *mut ffi::PyObject,
|
||||
_t: PhantomData<T>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<T> PyPtr<T> {
|
||||
/// Creates a PyPtr instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the Py.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr(ptr: *mut ffi::PyObject) -> PyPtr<T> {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
PyPtr {inner: ptr, _t: PhantomData}
|
||||
}
|
||||
|
||||
/// Creates a PyObject instance for the given FFI pointer.
|
||||
/// This moves ownership over the pointer into the PyObject.
|
||||
/// Returns None for null pointers; undefined behavior if the pointer is invalid.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_opt(_py: Python, ptr: *mut ffi::PyObject)
|
||||
-> Option<PyPtr<T>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(PyPtr::from_owned_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct PyPtr<PyObject> from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python, ptr: *mut ffi::PyObject) -> PyResult<PyPtr<T>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(PyPtr::from_owned_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to PyPtr pointer
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(ptr: *mut ffi::PyObject) -> PyPtr<T>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
PyPtr::from_owned_ptr(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a PyPtr instance for the given FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
/// Caller of this method has to have valid Python object.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr(ptr: *mut ffi::PyObject) -> PyPtr<T> {
|
||||
debug_assert!(!ptr.is_null() && ffi::Py_REFCNT(ptr) > 0);
|
||||
ffi::Py_INCREF(ptr);
|
||||
PyPtr {inner: ptr, _t: PhantomData}
|
||||
}
|
||||
|
||||
/// Creates a Py instance for the given FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr_opt(_py: Python,
|
||||
ptr: *mut ffi::PyObject) -> Option<PyPtr<T>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
debug_assert!(ffi::Py_REFCNT(ptr) > 0);
|
||||
ffi::Py_INCREF(ptr);
|
||||
Some(PyPtr{inner: ptr, _t: PhantomData})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_ref<'p>(&self, py: Python<'p>) -> Py<'p, T> {
|
||||
unsafe { Py::from_borrowed_ptr(py, self.inner) }
|
||||
}
|
||||
|
||||
pub fn into_ref<'p>(self, py: Python<'p>) -> Py<'p, T> {
|
||||
let p = Py{inner: self.inner, _t: PhantomData, py: py};
|
||||
std::mem::forget(self);
|
||||
p
|
||||
}
|
||||
|
||||
/// Converts PyPtr<T> -> PyPtr<PyObject>
|
||||
/// Converts PyPtr<T> -> pptr
|
||||
/// Consumes `self` without calling `Py_INCREF()`
|
||||
#[inline]
|
||||
pub fn park(self) -> pptr {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts PyPtr<T> -> &PyObject<'p>.
|
||||
/// 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) }
|
||||
|
@ -306,39 +230,32 @@ impl<T> PyPtr<T> {
|
|||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Gets the reference count of this PyPtr object.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self) -> usize {
|
||||
unsafe { ffi::Py_REFCNT(self.inner) as usize }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clone_ref(&self, _py: Python) -> PyPtr<T> {
|
||||
unsafe { PyPtr::from_borrowed_ptr(self.inner) }
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
/// Unchecked downcast from other PyPtr<S> to PyPtr<S>.
|
||||
/// Undefined behavior if the input object does not have the expected type.
|
||||
#[inline]
|
||||
pub unsafe fn unchecked_downcast_from<S>(py: PyPtr<S>) -> PyPtr<T>
|
||||
{
|
||||
let res = PyPtr {inner: py.inner, _t: PhantomData};
|
||||
std::mem::forget(py);
|
||||
res
|
||||
}
|
||||
|
||||
/// Casts the PyPtr to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_into<'p, D>(self, py: Python<'p>) -> Result<D, PyDowncastError<'p>>
|
||||
where D: ::PyDowncastInto<'p>
|
||||
{
|
||||
match <D as ::PyDowncastInto>::downcast_from_owned_ptr(py, self.inner) {
|
||||
Ok(ptr) => {
|
||||
std::mem::forget(self);
|
||||
Ok(ptr)
|
||||
}
|
||||
Err(e) => Err(e)
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -363,6 +280,21 @@ impl<T> IntoPythonPointer for PyPtr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
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]
|
||||
|
@ -371,7 +303,6 @@ impl<T> IntoPyObject for PyPtr<T> {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// 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> {}
|
||||
|
@ -406,42 +337,6 @@ impl<'p, T> Py<'p, T>
|
|||
Py {inner: ptr, _t: PhantomData, py: py}
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_panic(py: Python<'p>, ptr: *mut ffi::PyObject) -> Py<'p, T>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
::err::panic_after_error();
|
||||
} else {
|
||||
Py::from_owned_ptr(py, ptr)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_owned_ptr_or_opt(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Option<Py<'p, T>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Py::from_owned_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct Py<'p, PyObj> from the result of a Python FFI call that
|
||||
/// returns a new reference (owned pointer).
|
||||
/// Returns `Err(PyErr)` if the pointer is `null`.
|
||||
/// Unsafe because the pointer might be invalid.
|
||||
pub unsafe fn from_owned_ptr_or_err(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<Py<'p, T>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Ok(Py::from_owned_ptr(py, ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a Py instance for the given FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Undefined behavior if the pointer is NULL or invalid.
|
||||
|
@ -452,79 +347,25 @@ impl<'p, T> Py<'p, T>
|
|||
Py {inner: ptr, _t: PhantomData, py: py}
|
||||
}
|
||||
|
||||
/// Creates a Py instance for the given FFI pointer.
|
||||
/// Calls Py_INCREF() on the ptr.
|
||||
/// Convert tp `PyPtr<T>` pointer
|
||||
#[inline]
|
||||
pub unsafe fn from_borrowed_ptr_opt(py: Python<'p>,
|
||||
ptr: *mut ffi::PyObject) -> Option<Py<'p, T>> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
debug_assert!(ffi::Py_REFCNT(ptr) > 0);
|
||||
ffi::Py_INCREF(ptr);
|
||||
Some(Py {inner: ptr, _t: PhantomData, py: py})
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the reference count of this Py object.
|
||||
#[inline]
|
||||
pub fn get_refcnt(&self) -> usize {
|
||||
unsafe { ffi::Py_REFCNT(self.inner) as usize }
|
||||
}
|
||||
|
||||
/// Convert tp `pptr` pointer
|
||||
#[inline]
|
||||
pub fn park(self) -> pptr {
|
||||
pub fn park(self) -> PyPtr<T> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Creates a PyPtr instance. Calls Py_INCREF() on the ptr.
|
||||
/// Returns owned PyObject<'p> reference
|
||||
#[inline]
|
||||
pub fn as_pptr(&self) -> PyPtr<T> {
|
||||
unsafe {
|
||||
ffi::Py_INCREF(self.inner);
|
||||
}
|
||||
PyPtr { inner: self.inner, _t: PhantomData }
|
||||
}
|
||||
|
||||
/// Consumes a Py<T> instance and creates a PyPtr instance.
|
||||
/// Ownership moves over to the PyPtr<T> instance, Does not call Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub fn into_pptr(self) -> PyPtr<T> {
|
||||
let ptr = PyPtr { inner: self.inner, _t: PhantomData };
|
||||
std::mem::forget(self);
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Converts Py<'p, T> -> PyObject<'p>. Calls Py_INCREF() on the ptr.
|
||||
#[inline]
|
||||
pub fn as_pyobject(&self) -> &PyObject<'p> {
|
||||
pub fn as_object(&self) -> &'p PyObject<'p> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Converts Py<'p, T> -> PyObject<'p>
|
||||
/// Consumes `self` without calling `Py_DECREF()`
|
||||
#[inline]
|
||||
pub fn into_pyobject(self) -> PyObject<'p> {
|
||||
pub fn into_object(self) -> PyObject<'p> {
|
||||
unsafe { std::mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Unchecked downcast from other Py<S> to Py<S>.
|
||||
/// Undefined behavior if the input object does not have the expected type.
|
||||
#[inline]
|
||||
pub unsafe fn unchecked_downcast_from<'a, S>(ob: Py<'a, S>) -> Py<'a, T>
|
||||
{
|
||||
let res = Py {inner: ob.inner, _t: PhantomData, py: ob.py};
|
||||
std::mem::forget(ob);
|
||||
res
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clone_ref(&self) -> Py<'p, T> {
|
||||
unsafe { ffi::Py_INCREF(self.inner) };
|
||||
Py {inner: self.inner, _t: self._t, py: self.py}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn gil(&self) -> Python<'p> {
|
||||
self.py
|
||||
|
@ -542,61 +383,9 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
|
|||
Ok(Py{inner: ob, _t: PhantomData, py: py})
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub fn cast_from_borrowed_ptr(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<Py<'p, T>, ::PyDowncastError<'p>>
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 };
|
||||
|
||||
if checked {
|
||||
Ok( unsafe { Py::from_borrowed_ptr(py, ptr) })
|
||||
} else {
|
||||
Err(::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub fn cast_from_owned_ptr(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> Result<Py<'p, T>, ::PyDowncastError<'p>>
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 };
|
||||
|
||||
if checked {
|
||||
Ok( unsafe { Py::from_owned_ptr(py, ptr) })
|
||||
} else {
|
||||
Err(::PyDowncastError(py, None))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cast_from_owned_or_err(py: Python<'p>, ptr: *mut ffi::PyObject)
|
||||
-> PyResult<Py<'p, T>>
|
||||
{
|
||||
if ptr.is_null() {
|
||||
Err(PyErr::fetch(py))
|
||||
} else {
|
||||
Py::cast_from_owned_ptr(py, ptr).map_err(|e| e.into())
|
||||
}
|
||||
}
|
||||
|
||||
/// Cast from ffi::PyObject ptr to a concrete object.
|
||||
#[inline]
|
||||
pub unsafe fn cast_from_owned_ptr_or_panic(py: Python<'p>,
|
||||
ptr: *mut ffi::PyObject) -> Py<'p, T>
|
||||
{
|
||||
if ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 {
|
||||
Py::from_owned_ptr(py, ptr)
|
||||
} else {
|
||||
::err::panic_after_error();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_ref(&self) -> &T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
|
||||
unsafe {
|
||||
let ptr = (self.inner as *mut u8).offset(offset) as *mut T;
|
||||
ptr.as_ref().unwrap()
|
||||
|
@ -606,77 +395,11 @@ impl<'p, T> Py<'p, T> where T: PyTypeInfo
|
|||
#[inline]
|
||||
pub fn as_mut(&self) -> &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()
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast<D>(&self) -> Result<Py<'p, D>, PyDowncastError<'p>>
|
||||
where D: PyTypeInfo
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(self.inner, D::type_object()) != 0 };
|
||||
if checked {
|
||||
Ok( unsafe { Py::<D>::unchecked_downcast_from(self.clone_ref()) })
|
||||
} else {
|
||||
Err(PyDowncastError(self.py, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_into<D>(self) -> Result<Py<'p, D>, PyDowncastError<'p>>
|
||||
where D: 'p + PyTypeInfo
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(self.inner, D::type_object()) != 0 };
|
||||
if checked {
|
||||
Ok( unsafe { Py::<D>::unchecked_downcast_from(self) })
|
||||
} else {
|
||||
Err(PyDowncastError(self.py, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Casts the PyObject to a concrete Python object type.
|
||||
/// Fails with `PyDowncastError` if the object is not of the expected type.
|
||||
#[inline]
|
||||
pub fn cast_as<D>(&'p self) -> Result<&'p D, PyDowncastError<'p>>
|
||||
where D: PyTypeInfo
|
||||
{
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(self.inner, D::type_object()) != 0 };
|
||||
|
||||
if checked {
|
||||
Ok(
|
||||
unsafe {
|
||||
let offset = <D as PyTypeInfo>::offset();
|
||||
let ptr = (self.inner as *mut u8).offset(offset) as *mut D;
|
||||
ptr.as_ref().unwrap() })
|
||||
} else {
|
||||
Err(PyDowncastError(self.py, None))
|
||||
}
|
||||
}
|
||||
|
||||
/// Unchecked downcast from Py<'p, S> to &'p S.
|
||||
/// Undefined behavior if the input object does not have the expected type.
|
||||
#[inline]
|
||||
pub unsafe fn unchecked_downcast_borrow_from<'a, S>(py: &'a Py<'a, S>) -> &'a T {
|
||||
let offset = <T as PyTypeInfo>::offset();
|
||||
|
||||
let ptr = (py.inner as *mut u8).offset(offset) as *mut T;
|
||||
ptr.as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Extracts some type from the Python object.
|
||||
/// This is a wrapper function around `FromPyObject::extract()`.
|
||||
#[inline]
|
||||
pub fn extract<D>(&'p self) -> PyResult<D> where D: ::conversion::FromPyObject<'p>
|
||||
{
|
||||
::conversion::FromPyObject::extract(&self.as_pyobject())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, T> PythonObjectWithGilToken<'p> for Py<'p, T> {
|
||||
|
@ -757,31 +480,6 @@ impl<'p, T> AsMut<T> for Py<'p, T> where T: PyTypeInfo {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'source, T> ::FromPyObject<'source> for &'source T
|
||||
where T: PyTypeInfo + ::PyDowncastFrom<'source>
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(py: &'source PyObject<'source>) -> PyResult<&'source T>
|
||||
{
|
||||
Ok(py.cast_as()?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'source, T> ::FromPyObject<'source> for Py<'source, T> where T: PyTypeInfo
|
||||
{
|
||||
#[inline]
|
||||
default fn extract(py: &'source PyObject<'source>) -> PyResult<Py<'source, T>>
|
||||
{
|
||||
let ptr = py.as_ptr();
|
||||
let checked = unsafe { ffi::PyObject_TypeCheck(ptr, T::type_object()) != 0 };
|
||||
if checked {
|
||||
Ok( unsafe { Py::<T>::from_borrowed_ptr(py.gil(), ptr) })
|
||||
} else {
|
||||
Err(PyDowncastError(py.gil(), None).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a, T> ToPyObject for Py<'a, T> {
|
||||
|
||||
#[inline]
|
||||
|
@ -797,21 +495,6 @@ impl <'a, T> ToPyObject for Py<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
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<'p, T> IntoPyObject for Py<'p, T> {
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -12,7 +12,7 @@ use typeob::{PyTypeInfo, PyTypeObject, PyObjectAlloc};
|
|||
use token::{PythonToken};
|
||||
use objects::{PyObject, PyType, PyBool, PyDict, PyModule};
|
||||
use err::{PyErr, PyResult, PyDowncastError};
|
||||
use pointers::{Py, PyPtr, pptr};
|
||||
use pointers::{Py, pptr};
|
||||
use pythonrun::GILGuard;
|
||||
|
||||
|
||||
|
@ -52,21 +52,6 @@ pub trait PyDowncastInto<'p> : Sized {
|
|||
}
|
||||
|
||||
|
||||
pub trait PyClone : Sized {
|
||||
fn clone_ref(&self) -> PyPtr<Self>;
|
||||
}
|
||||
|
||||
impl<T> PyClone for T where T: ToPythonPointer {
|
||||
#[inline]
|
||||
fn clone_ref(&self) -> PyPtr<T> {
|
||||
unsafe {
|
||||
let ptr = <T as ToPythonPointer>::as_ptr(self);
|
||||
PyPtr::from_borrowed_ptr(ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// This trait allows retrieving the underlying FFI pointer from Python objects.
|
||||
pub trait ToPythonPointer {
|
||||
/// Retrieves the underlying FFI pointer (as a borrowed pointer).
|
||||
|
|
|
@ -74,7 +74,7 @@ struct EmptyClassWithNew {token: PythonToken<EmptyClassWithNew> }
|
|||
impl EmptyClassWithNew {
|
||||
#[__new__]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<PyPtr<EmptyClassWithNew>> {
|
||||
Ok(py.with_token(|t| EmptyClassWithNew{token: t}).into_pptr())
|
||||
Ok(py.with_token(|t| EmptyClassWithNew{token: t}).park())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ struct NewWithOneArg {
|
|||
impl NewWithOneArg {
|
||||
#[new]
|
||||
fn __new__(_cls: &PyType, py: Python, arg: i32) -> PyResult<PyPtr<NewWithOneArg>> {
|
||||
Ok(py.with_token(|t| NewWithOneArg{_data: arg, token: t}).into_pptr())
|
||||
Ok(py.with_token(|t| NewWithOneArg{_data: arg, token: t}).park())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +122,7 @@ impl NewWithTwoArgs {
|
|||
#[new]
|
||||
fn __new__(_cls: &PyType, py: Python, arg1: i32, arg2: i32)
|
||||
-> PyResult<PyPtr<NewWithTwoArgs>> {
|
||||
Ok(py.with_token(|t| NewWithTwoArgs{_data1: arg1, _data2: arg2, token: t}).into_pptr())
|
||||
Ok(py.with_token(|t| NewWithTwoArgs{_data1: arg1, _data2: arg2, token: t}).park())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,7 +274,7 @@ struct StaticMethod {token: PythonToken<StaticMethod>}
|
|||
impl StaticMethod {
|
||||
#[new]
|
||||
fn __new__(cls: &PyType, py: Python) -> PyResult<PyPtr<StaticMethod>> {
|
||||
Ok(py.with_token(|t| StaticMethod{token: t}).into_pptr())
|
||||
Ok(py.with_token(|t| StaticMethod{token: t}).park())
|
||||
}
|
||||
|
||||
//#[staticmethod]
|
||||
|
@ -343,7 +343,7 @@ fn gc_integration() {
|
|||
dropped: TestDropCall { drop_called: drop_called.clone() },
|
||||
token: t});
|
||||
|
||||
*inst.self_ref.borrow_mut() = inst.clone_ref().park();
|
||||
*inst.self_ref.borrow_mut() = inst.clone().park().park();
|
||||
drop(inst);
|
||||
|
||||
py.run("import gc; gc.collect()", None, None).unwrap();
|
||||
|
|
Loading…
Reference in New Issue