2015-01-05 16:05:53 +00:00
|
|
|
use std;
|
|
|
|
use ffi;
|
2015-01-07 00:40:48 +00:00
|
|
|
use python::{Python, PythonObject, PythonObjectWithCheckedDowncast, ToPythonPointer};
|
2015-01-11 17:56:59 +00:00
|
|
|
use objects::{exc, PyObject, PyBool, PyTuple};
|
2015-01-05 15:34:12 +00:00
|
|
|
use err::{self, PyErr, PyResult};
|
2015-01-05 16:05:53 +00:00
|
|
|
|
2015-04-18 22:39:04 +00:00
|
|
|
/// Conversion trait that allows various objects to be converted into python objects.
|
2015-01-11 17:56:59 +00:00
|
|
|
pub trait ToPyObject<'p> {
|
2015-01-05 20:14:01 +00:00
|
|
|
type ObjectType : PythonObject<'p> = PyObject<'p>;
|
2015-01-11 17:56:59 +00:00
|
|
|
|
2015-04-18 22:39:04 +00:00
|
|
|
/// Converts self into a python object.
|
2015-04-18 23:07:14 +00:00
|
|
|
fn to_py_object(&self, py: Python<'p>) -> Self::ObjectType;
|
2015-01-11 17:56:59 +00:00
|
|
|
|
2015-04-18 22:39:04 +00:00
|
|
|
/// Converts self into a python object.
|
|
|
|
///
|
|
|
|
/// May be more efficient than `to_py_object` in some cases because
|
|
|
|
/// it can move out of the input object.
|
2015-01-05 20:14:01 +00:00
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn into_py_object(self, py: Python<'p>) -> Self::ObjectType
|
2015-01-11 17:56:59 +00:00
|
|
|
where Self: Sized {
|
|
|
|
self.to_py_object(py)
|
|
|
|
}
|
|
|
|
|
2015-04-18 22:39:04 +00:00
|
|
|
/// Converts self into a python object and calls the specified closure
|
|
|
|
/// on the native FFI pointer underlying the python object.
|
|
|
|
///
|
|
|
|
/// May be more efficient than `to_py_object` because it does not need
|
|
|
|
/// to touch any reference counts when the input object already is a python object.
|
2015-01-11 17:56:59 +00:00
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn with_borrowed_ptr<F, R>(&self, py: Python<'p>, f: F) -> R
|
|
|
|
where F: FnOnce(*mut ffi::PyObject) -> R {
|
|
|
|
let obj = self.to_py_object(py);
|
2015-01-07 00:40:48 +00:00
|
|
|
f(ToPythonPointer::as_ptr(&obj))
|
2015-01-05 20:14:01 +00:00
|
|
|
}
|
2015-01-11 17:56:59 +00:00
|
|
|
|
2015-01-05 20:14:01 +00:00
|
|
|
// FFI functions that accept a borrowed reference will use:
|
2015-01-11 17:56:59 +00:00
|
|
|
// input.with_borrowed_ptr(|obj| ffi::Call(obj)
|
2015-01-05 20:14:01 +00:00
|
|
|
// 1) input is &PyObject
|
2015-01-11 17:56:59 +00:00
|
|
|
// -> with_borrowed_ptr() just forwards to the closure
|
|
|
|
// 2) input is PyObject
|
|
|
|
// -> with_borrowed_ptr() just forwards to the closure
|
2015-01-05 20:14:01 +00:00
|
|
|
// 3) input is &str, int, ...
|
2015-04-18 22:39:04 +00:00
|
|
|
// -> to_py_object() allocates new python object; FFI call happens; PyObject::drop() calls Py_DECREF()
|
2015-01-05 15:34:12 +00:00
|
|
|
|
2015-01-05 20:14:01 +00:00
|
|
|
// FFI functions that steal a reference will use:
|
2015-01-11 17:56:59 +00:00
|
|
|
// let input = try!(input.into_py_object()); ffi::Call(input.steal_ptr())
|
2015-01-05 20:14:01 +00:00
|
|
|
// 1) input is &PyObject
|
2015-01-11 17:56:59 +00:00
|
|
|
// -> into_py_object() calls Py_INCREF
|
|
|
|
// 2) input is PyObject
|
|
|
|
// -> into_py_object() is no-op
|
2015-01-05 20:14:01 +00:00
|
|
|
// 3) input is &str, int, ...
|
2015-01-11 17:56:59 +00:00
|
|
|
// -> into_py_object() allocates new python object
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
|
|
|
|
2015-01-04 01:54:54 +00:00
|
|
|
/// FromPyObject is implemented by various types that can be extracted from a python object.
|
|
|
|
pub trait FromPyObject<'p, 's> {
|
|
|
|
fn from_py_object(s: &'s PyObject<'p>) -> PyResult<'p, Self>;
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// PyObject, PyModule etc.
|
2015-01-07 00:40:48 +00:00
|
|
|
// We support FromPyObject and ToPyObject for owned python references.
|
2015-01-05 16:05:53 +00:00
|
|
|
// This allows using existing python objects in code that generically expects a value
|
|
|
|
// convertible to a python object.
|
2015-01-04 01:54:54 +00:00
|
|
|
|
2015-04-18 23:07:14 +00:00
|
|
|
/// Identity conversion: allows using existing `PyObject` instances where
|
|
|
|
/// `ToPyObject` is expected.
|
|
|
|
impl <'p, 's> ToPyObject<'p> for PyObject<'s> {
|
2015-04-18 20:20:19 +00:00
|
|
|
type ObjectType = PyObject<'p>;
|
2015-01-11 17:56:59 +00:00
|
|
|
|
2015-01-04 23:07:31 +00:00
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn to_py_object(&self, py: Python<'p>) -> PyObject<'p> {
|
|
|
|
self.clone().into_py_object(py)
|
2015-01-11 17:56:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn into_py_object(self, py: Python<'p>) -> PyObject<'p> {
|
|
|
|
// Transmute the lifetime.
|
|
|
|
// This is safe, because both lifetime variables represent the same lifetime:
|
|
|
|
// that of the python GIL acquisition.
|
|
|
|
unsafe { std::mem::transmute(self) }
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
2015-01-11 17:56:59 +00:00
|
|
|
|
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn with_borrowed_ptr<F, R>(&self, py: Python<'p>, f: F) -> R
|
|
|
|
where F: FnOnce(*mut ffi::PyObject) -> R {
|
2015-01-11 17:56:59 +00:00
|
|
|
f(self.as_ptr())
|
|
|
|
}
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
|
|
|
|
2015-01-07 00:40:48 +00:00
|
|
|
impl <'p, 's, T> FromPyObject<'p, 's> for T where T: PythonObjectWithCheckedDowncast<'p> {
|
2015-01-05 16:05:53 +00:00
|
|
|
#[inline]
|
2015-01-07 00:40:48 +00:00
|
|
|
fn from_py_object(s : &'s PyObject<'p>) -> PyResult<'p, T> {
|
|
|
|
Ok(try!(s.clone().cast_into()))
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-07 00:40:48 +00:00
|
|
|
// &PyObject, &PyModule etc.
|
|
|
|
// We support FromPyObject and ToPyObject for borrowed python references.
|
2015-01-05 16:05:53 +00:00
|
|
|
// This allows using existing python objects in code that generically expects a value
|
2015-01-07 00:40:48 +00:00
|
|
|
// convertible to a python object.
|
2015-01-11 17:56:59 +00:00
|
|
|
impl <'p, 's, T> ToPyObject<'p> for &'s T where T : ToPyObject<'p> {
|
2015-04-18 23:07:14 +00:00
|
|
|
type ObjectType = T::ObjectType;
|
2015-01-04 01:54:54 +00:00
|
|
|
|
2015-01-04 19:11:18 +00:00
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn to_py_object(&self, py: Python<'p>) -> T::ObjectType {
|
2015-01-11 17:56:59 +00:00
|
|
|
(**self).to_py_object(py)
|
2015-01-04 19:11:18 +00:00
|
|
|
}
|
2015-01-05 16:05:53 +00:00
|
|
|
|
2015-01-11 17:56:59 +00:00
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn into_py_object(self, py: Python<'p>) -> T::ObjectType {
|
2015-01-11 17:56:59 +00:00
|
|
|
(*self).to_py_object(py)
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
|
|
|
|
2015-01-11 17:56:59 +00:00
|
|
|
#[inline]
|
2015-04-18 23:07:14 +00:00
|
|
|
fn with_borrowed_ptr<F, R>(&self, py: Python<'p>, f: F) -> R
|
|
|
|
where F: FnOnce(*mut ffi::PyObject) -> R {
|
2015-01-11 17:56:59 +00:00
|
|
|
(**self).with_borrowed_ptr(py, f)
|
2015-01-05 16:05:53 +00:00
|
|
|
}
|
|
|
|
}
|
2015-04-18 20:20:19 +00:00
|
|
|
|
2015-01-05 16:05:53 +00:00
|
|
|
|