diff --git a/Cargo.toml b/Cargo.toml index a0bc4c7c4..a0af50c10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,10 @@ license-file = "LICENSE" [dependencies] libc = "0.2" -cpython = "0.1" -python3-sys = "0.1" num-complex = "0.1" ndarray = "0.10" + +[dependencies.pyo3] +git = "http://github.com/termoshtt/pyo3" +branch = "pyobject_macros" +version = "0.2" diff --git a/example/extensions/Cargo.toml b/example/extensions/Cargo.toml index 78b3e8a47..b8fd62d8b 100644 --- a/example/extensions/Cargo.toml +++ b/example/extensions/Cargo.toml @@ -9,5 +9,8 @@ crate-type = ["cdylib"] [dependencies] numpy = { path = "../.." } -cpython = "0.1" ndarray = "0.10" + +[dependencies.pyo3] +version = "*" +features = ["extension-module"] diff --git a/example/extensions/src/lib.rs b/example/extensions/src/lib.rs index 83dd0a488..3ddc5045d 100644 --- a/example/extensions/src/lib.rs +++ b/example/extensions/src/lib.rs @@ -1,48 +1,41 @@ +#![feature(proc_macro, proc_macro_path_invoc, specialization)] -#[macro_use] -extern crate cpython; -extern crate numpy; extern crate ndarray; +extern crate numpy; +extern crate pyo3; -use numpy::*; use ndarray::*; -use cpython::{PyResult, Python, PyObject}; - -/* Pure rust-ndarray functions */ - -// immutable example -fn axpy(a: f64, x: ArrayViewD, y: ArrayViewD) -> ArrayD { - a * &x + &y -} - -// mutable example (no return) -fn mult(a: f64, mut x: ArrayViewMutD) { - x *= a; -} - -/* rust-cpython wrappers (to be exposed) */ - -// wrapper of `axpy` -fn axpy_py(py: Python, a: f64, x: PyArray, y: PyArray) -> PyResult { - let np = PyArrayModule::import(py)?; - let x = x.as_array().into_pyresult(py, "x must be f64 array")?; - let y = y.as_array().into_pyresult(py, "y must be f64 array")?; - Ok(axpy(a, x, y).into_pyarray(py, &np)) -} - -// wrapper of `mult` -fn mult_py(py: Python, a: f64, x: PyArray) -> PyResult { - let x = x.as_array_mut().into_pyresult(py, "x must be f64 array")?; - mult(a, x); - Ok(py.None()) // Python function must returns -} +use numpy::*; +use pyo3::{py, PyModule, PyObject, PyResult, Python}; + +#[py::modinit(rust_ext)] +fn init_module(py: Python, m: &PyModule) -> PyResult<()> { + // immutable example + fn axpy(a: f64, x: ArrayViewD, y: ArrayViewD) -> ArrayD { + a * &x + &y + } + + // mutable example (no return) + fn mult(a: f64, mut x: ArrayViewMutD) { + x *= a; + } + + // wrapper of `axpy` + #[pyfn(m, "axpy")] + fn axpy_py(py: Python, a: f64, x: PyArray, y: PyArray) -> PyResult { + let np = PyArrayModule::import(py)?; + let x = x.as_array().into_pyresult(py, "x must be f64 array")?; + let y = y.as_array().into_pyresult(py, "y must be f64 array")?; + Ok(axpy(a, x, y).into_pyarray(py, &np)) + } + + // wrapper of `mult` + #[pyfn(m, "mult")] + fn mult_py(py: Python, a: f64, x: PyArray) -> PyResult { + let x = x.as_array_mut().into_pyresult(py, "x must be f64 array")?; + mult(a, x); + Ok(py.None()) // Python function must returns + } -/* Define module "_rust_ext" */ -py_module_initializer!(_rust_ext, init_rust_ext, PyInit__rust_ext, |py, m| { - m.add(py, "__doc__", "Rust extension for NumPy")?; - m.add(py, - "axpy", - py_fn!(py, axpy_py(a: f64, x: PyArray, y: PyArray)))?; - m.add(py, "mult", py_fn!(py, mult_py(a: f64, x: PyArray)))?; Ok(()) -}); +} diff --git a/src/array.rs b/src/array.rs index 9f09393ab..606110249 100644 --- a/src/array.rs +++ b/src/array.rs @@ -1,34 +1,32 @@ //! Untyped safe interface for NumPy ndarray -use npyffi; -use pyffi; -use cpython::*; use ndarray::*; +use npyffi; +use pyo3::ffi; +use pyo3::*; use std::os::raw::c_void; use std::ptr::null_mut; -use super::*; use super::error::ArrayCastError; +use super::*; /// Untyped safe interface for NumPy ndarray. pub struct PyArray(PyObject); -impl PyArray { - pub fn as_ptr(&self) -> *mut npyffi::PyArrayObject { - self.0.as_ptr() as *mut npyffi::PyArrayObject - } +pyobject_native_type!(PyArray, npyffi::PyArray_Type, npyffi::PyArray_Check); - pub fn steal_ptr(self) -> *mut npyffi::PyArrayObject { - self.0.steal_ptr() as *mut npyffi::PyArrayObject +impl PyArray { + pub fn as_array_ptr(&self) -> *mut npyffi::PyArrayObject { + self.as_ptr() as _ } - pub unsafe fn from_owned_ptr(py: Python, ptr: *mut pyffi::PyObject) -> Self { + pub unsafe fn from_owned_ptr(py: Python, ptr: *mut pyo3::ffi::PyObject) -> Self { let obj = PyObject::from_owned_ptr(py, ptr); PyArray(obj) } - pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut pyffi::PyObject) -> Self { + pub unsafe fn from_borrowed_ptr(py: Python, ptr: *mut pyo3::ffi::PyObject) -> Self { let obj = PyObject::from_borrowed_ptr(py, ptr); PyArray(obj) } @@ -37,7 +35,7 @@ impl PyArray { /// /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_NDIM pub fn ndim(&self) -> usize { - let ptr = self.as_ptr(); + let ptr = self.as_array_ptr(); unsafe { (*ptr).nd as usize } } @@ -46,7 +44,7 @@ impl PyArray { /// https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_DIMS pub fn dims(&self) -> Vec { let n = self.ndim(); - let ptr = self.as_ptr(); + let ptr = self.as_array_ptr(); let dims = unsafe { let p = (*ptr).dimensions; ::std::slice::from_raw_parts(p, n) @@ -69,7 +67,7 @@ impl PyArray { /// - https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.strides.html#numpy.ndarray.strides pub fn strides(&self) -> Vec { let n = self.ndim(); - let ptr = self.as_ptr(); + let ptr = self.as_array_ptr(); let dims = unsafe { let p = (*ptr).strides; ::std::slice::from_raw_parts(p, n) @@ -78,21 +76,23 @@ impl PyArray { } unsafe fn data(&self) -> *mut T { - let ptr = self.as_ptr(); + let ptr = self.as_array_ptr(); (*ptr).data as *mut T } fn ndarray_shape(&self) -> StrideShape { // FIXME may be done more simply let shape: Shape<_> = Dim(self.shape()).into(); - let st: Vec = - self.strides().iter().map(|&x| x as usize / ::std::mem::size_of::()).collect(); + let st: Vec = self.strides() + .iter() + .map(|&x| x as usize / ::std::mem::size_of::()) + .collect(); shape.strides(Dim(st)) } pub fn typenum(&self) -> i32 { unsafe { - let descr = (*self.as_ptr()).descr; + let descr = (*self.as_array_ptr()).descr; (*descr).type_num } } @@ -110,13 +110,23 @@ impl PyArray { /// Get data as a ndarray::ArrayView pub fn as_array(&self) -> Result, ArrayCastError> { self.type_check::()?; - unsafe { Ok(ArrayView::from_shape_ptr(self.ndarray_shape::(), self.data())) } + unsafe { + Ok(ArrayView::from_shape_ptr( + self.ndarray_shape::(), + self.data(), + )) + } } /// Get data as a ndarray::ArrayViewMut pub fn as_array_mut(&self) -> Result, ArrayCastError> { self.type_check::()?; - unsafe { Ok(ArrayViewMut::from_shape_ptr(self.ndarray_shape::(), self.data())) } + unsafe { + Ok(ArrayViewMut::from_shape_ptr( + self.ndarray_shape::(), + self.data(), + )) + } } /// Get data as a Rust immutable slice @@ -131,23 +141,25 @@ impl PyArray { unsafe { Ok(::std::slice::from_raw_parts_mut(self.data(), self.len())) } } - pub unsafe fn new_(py: Python, - np: &PyArrayModule, - dims: &[usize], - strides: *mut npy_intp, - data: *mut c_void) - -> Self { + pub unsafe fn new_( + py: Python, + np: &PyArrayModule, + dims: &[usize], + strides: *mut npy_intp, + data: *mut c_void, + ) -> Self { let dims: Vec<_> = dims.iter().map(|d| *d as npy_intp).collect(); - let ptr = np.PyArray_New(np.get_type_object(npyffi::ArrayType::PyArray_Type), - dims.len() as i32, - dims.as_ptr() as *mut npy_intp, - T::typenum(), - strides, - data, - 0, // itemsize - 0, // flag - ::std::ptr::null_mut() //obj - ); + let ptr = np.PyArray_New( + np.get_type_object(npyffi::ArrayType::PyArray_Type), + dims.len() as i32, + dims.as_ptr() as *mut npy_intp, + T::typenum(), + strides, + data, + 0, // itemsize + 0, // flag + ::std::ptr::null_mut(), //obj + ); Self::from_owned_ptr(py, ptr) } @@ -157,102 +169,36 @@ impl PyArray { } /// a wrapper of [PyArray_ZEROS](https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_ZEROS) - pub fn zeros(py: Python, - np: &PyArrayModule, - dims: &[usize], - order: NPY_ORDER) - -> Self { + pub fn zeros( + py: Python, + np: &PyArrayModule, + dims: &[usize], + order: NPY_ORDER, + ) -> Self { let dims: Vec = dims.iter().map(|d| *d as npy_intp).collect(); unsafe { let descr = np.PyArray_DescrFromType(T::typenum()); - let ptr = np.PyArray_Zeros(dims.len() as i32, - dims.as_ptr() as *mut npy_intp, - descr, - order as i32); + let ptr = np.PyArray_Zeros( + dims.len() as i32, + dims.as_ptr() as *mut npy_intp, + descr, + order as i32, + ); Self::from_owned_ptr(py, ptr) } } /// a wrapper of [PyArray_Arange](https://docs.scipy.org/doc/numpy/reference/c-api.array.html#c.PyArray_Arange) - pub fn arange(py: Python, - np: &PyArrayModule, - start: f64, - stop: f64, - step: f64) - -> Self { + pub fn arange( + py: Python, + np: &PyArrayModule, + start: f64, + stop: f64, + step: f64, + ) -> Self { unsafe { let ptr = np.PyArray_Arange(start, stop, step, T::typenum()); Self::from_owned_ptr(py, ptr) } } } - -impl<'source> FromPyObject<'source> for PyArray { - fn extract(py: Python, obj: &'source PyObject) -> PyResult { - Ok(obj.clone_ref(py).cast_into::(py)?) - } -} - -impl<'source> FromPyObject<'source> for &'source PyArray { - fn extract(py: Python, obj: &'source PyObject) -> PyResult { - Ok(obj.cast_as::(py)?) - } -} - -impl ToPyObject for PyArray { - type ObjectType = Self; - - fn to_py_object(&self, py: Python) -> Self { - PyClone::clone_ref(self, py) - } -} - -impl PythonObject for PyArray { - #[inline] - fn as_object(&self) -> &PyObject { - &self.0 - } - - #[inline] - fn into_object(self) -> PyObject { - self.0 - } - - #[inline] - unsafe fn unchecked_downcast_from(obj: PyObject) -> Self { - PyArray(obj) - } - - #[inline] - unsafe fn unchecked_downcast_borrow_from<'a>(obj: &'a PyObject) -> &'a Self { - ::std::mem::transmute(obj) - } -} - -impl PythonObjectWithCheckedDowncast for PyArray { - fn downcast_from<'p>(py: Python<'p>, - obj: PyObject) - -> Result> { - let np = PyArrayModule::import(py).unwrap(); - unsafe { - if npyffi::PyArray_Check(&np, obj.as_ptr()) != 0 { - Ok(PyArray(obj)) - } else { - Err(PythonObjectDowncastError(py)) - } - } - } - - fn downcast_borrow_from<'a, 'p>(py: Python<'p>, - obj: &'a PyObject) - -> Result<&'a PyArray, PythonObjectDowncastError<'p>> { - let np = PyArrayModule::import(py).unwrap(); - unsafe { - if npyffi::PyArray_Check(&np, obj.as_ptr()) != 0 { - Ok(::std::mem::transmute(obj)) - } else { - Err(PythonObjectDowncastError(py)) - } - } - } -} diff --git a/src/convert.rs b/src/convert.rs index 8685d2804..79d415521 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -1,11 +1,10 @@ - -use cpython::Python; use ndarray::*; +use pyo3::Python; -use std::os::raw::c_void; -use std::ptr::null_mut; use std::iter::Iterator; use std::mem::size_of; +use std::os::raw::c_void; +use std::ptr::null_mut; use super::*; @@ -44,7 +43,8 @@ pub trait ToPyArray { } impl ToPyArray for Iter - where Iter: Iterator + Sized +where + Iter: Iterator + Sized, { fn to_pyarray(self, py: Python, np: &PyArrayModule) -> PyArray { let vec: Vec = self.collect(); diff --git a/src/error.rs b/src/error.rs index 710c7defb..366483b45 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,22 +1,22 @@ //! Define Errors +use pyo3::*; use std::error; use std::fmt; -use cpython::*; pub trait IntoPyErr { - fn into_pyerr(self, py: Python, msg: &str) -> PyErr; + fn into_pyerr(self, msg: &str) -> PyErr; } pub trait IntoPyResult { type ValueType; - fn into_pyresult(self, py: Python, message: &str) -> PyResult; + fn into_pyresult(self, msg: &str) -> PyResult; } impl IntoPyResult for Result { type ValueType = T; - fn into_pyresult(self, py: Python, msg: &str) -> PyResult { - self.map_err(|e| e.into_pyerr(py, msg)) + fn into_pyresult(self, msg: &str) -> PyResult { + self.map_err(|e| e.into_pyerr(msg)) } } @@ -49,8 +49,8 @@ impl error::Error for ArrayCastError { } impl IntoPyErr for ArrayCastError { - fn into_pyerr(self, py: Python, msg: &str) -> PyErr { + fn into_pyerr(self, msg: &str) -> PyErr { let msg = format!("rust_numpy::ArrayCastError: {}", msg); - PyErr::new::(py, msg) + PyErr::new::(msg) } } diff --git a/src/lib.rs b/src/lib.rs index 80c4fef1e..c87f6ed60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,18 +1,19 @@ +#![feature(specialization)] -extern crate python3_sys as pyffi; -extern crate cpython; extern crate libc; -extern crate num_complex; extern crate ndarray; +extern crate num_complex; +#[macro_use] +extern crate pyo3; -pub mod types; pub mod array; -pub mod npyffi; -pub mod error; pub mod convert; +pub mod error; +pub mod npyffi; +pub mod types; pub use array::PyArray; -pub use types::*; -pub use error::*; pub use convert::{IntoPyArray, ToPyArray}; +pub use error::*; pub use npyffi::{PyArrayModule, PyUFuncModule}; +pub use types::*; diff --git a/src/npyffi/array.rs b/src/npyffi/array.rs index 8570e0e67..a1d0e742f 100644 --- a/src/npyffi/array.rs +++ b/src/npyffi/array.rs @@ -2,14 +2,14 @@ //! //! https://docs.scipy.org/doc/numpy/reference/c-api.array.html -use std::os::raw::*; -use std::ptr::null_mut; use libc::FILE; use std::ops::Deref; +use std::os::raw::*; +use std::ptr::null_mut; -use pyffi; -use pyffi::{PyObject, PyTypeObject}; -use cpython::{Python, PythonObject, ObjectProtocol, PyResult, PyModule}; +use pyo3::ffi; +use pyo3::ffi::{PyObject, PyTypeObject}; +use pyo3::{ObjectProtocol, PyModule, PyResult, Python, ToPyPointer}; use npyffi::*; @@ -20,15 +20,15 @@ use npyffi::*; /// Some APIs (including most accessor) in the above URL are not implemented /// since they are defined as C macro, and cannot be called from rust. /// Some of these are implemented on the high-level interface as a Rust function. -pub struct PyArrayModule { - numpy: PyModule, +pub struct PyArrayModule<'py> { + numpy: &'py PyModule, api: *const *const c_void, } -impl Deref for PyArrayModule { +impl<'py> Deref for PyArrayModule<'py> { type Target = PyModule; fn deref(&self) -> &Self::Target { - &self.numpy + self.numpy } } @@ -42,14 +42,13 @@ pub unsafe fn $fname(&self, $($arg : $t), *) $( -> $ret )* { } }} // pyarray_api! -impl PyArrayModule { +impl<'py> PyArrayModule<'py> { /// Import `numpy.core.multiarray` to use Array API. - pub fn import(py: Python) -> PyResult { + pub fn import(py: Python<'py>) -> PyResult { let numpy = py.import("numpy.core.multiarray")?; - let c_api = numpy.as_object().getattr(py, "_ARRAY_API")?; + let c_api = numpy.getattr("_ARRAY_API")?; let api = unsafe { - pyffi::PyCapsule_GetPointer(c_api.as_object().as_ptr(), null_mut()) as - *const *const c_void + ffi::PyCapsule_GetPointer(c_api.as_ptr(), null_mut()) as *const *const c_void }; Ok(Self { numpy: numpy, @@ -322,7 +321,7 @@ macro_rules! impl_array_type { #[allow(non_camel_case_types)] #[repr(i32)] pub enum ArrayType { $($tname),* } -impl PyArrayModule { +impl<'py> PyArrayModule<'py> { pub unsafe fn get_type_object(&self, ty: ArrayType) -> *mut PyTypeObject { match ty { $( ArrayType::$tname => *(self.api.offset($offset)) as *mut PyTypeObject ),* @@ -331,52 +330,54 @@ impl PyArrayModule { } }} // impl_array_type!; -impl_array_type!((1, PyBigArray_Type), - (2, PyArray_Type), - (3, PyArrayDescr_Type), - (4, PyArrayFlags_Type), - (5, PyArrayIter_Type), - (6, PyArrayMultiIter_Type), - (7, NPY_NUMUSERTYPES), - (8, PyBoolArrType_Type), - (9, _PyArrayScalar_BoolValues), - (10, PyGenericArrType_Type), - (11, PyNumberArrType_Type), - (12, PyIntegerArrType_Type), - (13, PySignedIntegerArrType_Type), - (14, PyUnsignedIntegerArrType_Type), - (15, PyInexactArrType_Type), - (16, PyFloatingArrType_Type), - (17, PyComplexFloatingArrType_Type), - (18, PyFlexibleArrType_Type), - (19, PyCharacterArrType_Type), - (20, PyByteArrType_Type), - (21, PyShortArrType_Type), - (22, PyIntArrType_Type), - (23, PyLongArrType_Type), - (24, PyLongLongArrType_Type), - (25, PyUByteArrType_Type), - (26, PyUShortArrType_Type), - (27, PyUIntArrType_Type), - (28, PyULongArrType_Type), - (29, PyULongLongArrType_Type), - (30, PyFloatArrType_Type), - (31, PyDoubleArrType_Type), - (32, PyLongDoubleArrType_Type), - (33, PyCFloatArrType_Type), - (34, PyCDoubleArrType_Type), - (35, PyCLongDoubleArrType_Type), - (36, PyObjectArrType_Type), - (37, PyStringArrType_Type), - (38, PyUnicodeArrType_Type), - (39, PyVoidArrType_Type)); +impl_array_type!( + (1, PyBigArray_Type), + (2, PyArray_Type), + (3, PyArrayDescr_Type), + (4, PyArrayFlags_Type), + (5, PyArrayIter_Type), + (6, PyArrayMultiIter_Type), + (7, NPY_NUMUSERTYPES), + (8, PyBoolArrType_Type), + (9, _PyArrayScalar_BoolValues), + (10, PyGenericArrType_Type), + (11, PyNumberArrType_Type), + (12, PyIntegerArrType_Type), + (13, PySignedIntegerArrType_Type), + (14, PyUnsignedIntegerArrType_Type), + (15, PyInexactArrType_Type), + (16, PyFloatingArrType_Type), + (17, PyComplexFloatingArrType_Type), + (18, PyFlexibleArrType_Type), + (19, PyCharacterArrType_Type), + (20, PyByteArrType_Type), + (21, PyShortArrType_Type), + (22, PyIntArrType_Type), + (23, PyLongArrType_Type), + (24, PyLongLongArrType_Type), + (25, PyUByteArrType_Type), + (26, PyUShortArrType_Type), + (27, PyUIntArrType_Type), + (28, PyULongArrType_Type), + (29, PyULongLongArrType_Type), + (30, PyFloatArrType_Type), + (31, PyDoubleArrType_Type), + (32, PyLongDoubleArrType_Type), + (33, PyCFloatArrType_Type), + (34, PyCDoubleArrType_Type), + (35, PyCLongDoubleArrType_Type), + (36, PyObjectArrType_Type), + (37, PyStringArrType_Type), + (38, PyUnicodeArrType_Type), + (39, PyVoidArrType_Type) +); #[allow(non_snake_case)] pub unsafe fn PyArray_Check(np: &PyArrayModule, op: *mut PyObject) -> c_int { - pyffi::PyObject_TypeCheck(op, np.get_type_object(ArrayType::PyArray_Type)) + ffi::PyObject_TypeCheck(op, np.get_type_object(ArrayType::PyArray_Type)) } #[allow(non_snake_case)] pub unsafe fn PyArray_CheckExact(np: &PyArrayModule, op: *mut PyObject) -> c_int { - (pyffi::Py_TYPE(op) == np.get_type_object(ArrayType::PyArray_Type)) as c_int + (ffi::Py_TYPE(op) == np.get_type_object(ArrayType::PyArray_Type)) as c_int } diff --git a/src/npyffi/mod.rs b/src/npyffi/mod.rs index 4d7b29f53..adf02b249 100644 --- a/src/npyffi/mod.rs +++ b/src/npyffi/mod.rs @@ -7,14 +7,14 @@ //! basic usage of Python C API, especially for the reference counting. //! //! - http://docs.python.jp/3/c-api/ -//! - http://dgrunwald.github.io/rust-cpython/doc/cpython/ +//! - http://dgrunwald.github.io/rust-pyo3/doc/pyo3/ -pub mod types; -pub mod objects; pub mod array; +pub mod objects; +pub mod types; pub mod ufunc; -pub use self::types::*; -pub use self::objects::*; pub use self::array::*; +pub use self::objects::*; +pub use self::types::*; pub use self::ufunc::*; diff --git a/src/npyffi/objects.rs b/src/npyffi/objects.rs index 190219ccc..61bea1f4f 100644 --- a/src/npyffi/objects.rs +++ b/src/npyffi/objects.rs @@ -4,9 +4,9 @@ #![allow(non_camel_case_types, non_snake_case)] use libc::FILE; -use pyffi::*; -use std::os::raw::*; +use pyo3::ffi::*; use std::option::Option; +use std::os::raw::*; use super::types::*; @@ -80,102 +80,92 @@ pub struct PyArray_ArrFuncs { pub argmin: PyArray_ArgFunc, } -pub type PyArray_GetItemFunc = Option *mut PyObject>; -pub type PyArray_SetItemFunc = Option c_int>; -pub type PyArray_CopySwapNFunc = Option; -pub type PyArray_CopySwapFunc = Option; +pub type PyArray_GetItemFunc = + Option *mut PyObject>; +pub type PyArray_SetItemFunc = + Option c_int>; +pub type PyArray_CopySwapNFunc = Option< + unsafe extern "C" fn( + *mut c_void, + npy_intp, + *mut c_void, + npy_intp, + npy_intp, + c_int, + *mut c_void, + ), +>; +pub type PyArray_CopySwapFunc = + Option; pub type PyArray_NonzeroFunc = Option c_uchar>; -pub type PyArray_CompareFunc = Option c_int>; -pub type PyArray_ArgFunc = Option c_int>; -pub type PyArray_DotFunc = Option; -pub type PyArray_VectorUnaryFunc = Option; -pub type PyArray_ScanFunc = Option c_int>; -pub type PyArray_FromStrFunc = Option c_int>; -pub type PyArray_FillFunc = Option c_int>; -pub type PyArray_SortFunc = Option c_int>; -pub type PyArray_ArgSortFunc = Option c_int>; -pub type PyArray_PartitionFunc = Option c_int>; -pub type PyArray_ArgPartitionFunc = Option c_int>; -pub type PyArray_FillWithScalarFunc = Option c_int>; +pub type PyArray_CompareFunc = + Option c_int>; +pub type PyArray_ArgFunc = + Option c_int>; +pub type PyArray_DotFunc = Option< + unsafe extern "C" fn( + *mut c_void, + npy_intp, + *mut c_void, + npy_intp, + *mut c_void, + npy_intp, + *mut c_void, + ), +>; +pub type PyArray_VectorUnaryFunc = + Option; +pub type PyArray_ScanFunc = + Option c_int>; +pub type PyArray_FromStrFunc = Option< + unsafe extern "C" fn(*mut c_char, *mut c_void, *mut *mut c_char, *mut PyArray_Descr) -> c_int, +>; +pub type PyArray_FillFunc = + Option c_int>; +pub type PyArray_SortFunc = + Option c_int>; +pub type PyArray_ArgSortFunc = + Option c_int>; +pub type PyArray_PartitionFunc = Option< + unsafe extern "C" fn( + *mut c_void, + npy_intp, + npy_intp, + *mut npy_intp, + *mut npy_intp, + *mut c_void, + ) -> c_int, +>; +pub type PyArray_ArgPartitionFunc = Option< + unsafe extern "C" fn( + *mut c_void, + *mut npy_intp, + npy_intp, + npy_intp, + *mut npy_intp, + *mut npy_intp, + *mut c_void, + ) -> c_int, +>; +pub type PyArray_FillWithScalarFunc = + Option c_int>; pub type PyArray_ScalarKindFunc = Option c_int>; -pub type PyArray_FastClipFunc = Option; -pub type PyArray_FastPutmaskFunc = Option; -pub type PyArray_FastTakeFunc = Option c_int>; +pub type PyArray_FastClipFunc = + Option; +pub type PyArray_FastPutmaskFunc = + Option; +pub type PyArray_FastTakeFunc = Option< + unsafe extern "C" fn( + *mut c_void, + *mut c_void, + *mut npy_intp, + npy_intp, + npy_intp, + npy_intp, + npy_intp, + NPY_CLIPMODE, + ) -> c_int, +>; #[repr(C)] #[derive(Clone, Copy)] @@ -248,39 +238,48 @@ pub struct PyUFuncObject { pub iter_flags: npy_uint32, } -pub type PyUFuncGenericFunction = Option; -pub type PyUFunc_MaskedStridedInnerLoopFunc = Option; -pub type PyUFunc_TypeResolutionFunc = Option c_int>; -pub type PyUFunc_LegacyInnerLoopSelectionFunc = - Option c_int>; -pub type PyUFunc_MaskedInnerLoopSelectionFunc = - Option c_int>; +pub type PyUFuncGenericFunction = + Option; +pub type PyUFunc_MaskedStridedInnerLoopFunc = Option< + unsafe extern "C" fn( + *mut *mut c_char, + *mut npy_intp, + *mut c_char, + npy_intp, + npy_intp, + *mut NpyAuxData, + ), +>; +pub type PyUFunc_TypeResolutionFunc = Option< + unsafe extern "C" fn( + *mut PyUFuncObject, + NPY_CASTING, + *mut *mut PyArrayObject, + *mut PyObject, + *mut *mut PyArray_Descr, + ) -> c_int, +>; +pub type PyUFunc_LegacyInnerLoopSelectionFunc = Option< + unsafe extern "C" fn( + *mut PyUFuncObject, + *mut *mut PyArray_Descr, + *mut PyUFuncGenericFunction, + *mut *mut c_void, + *mut c_int, + ) -> c_int, +>; +pub type PyUFunc_MaskedInnerLoopSelectionFunc = Option< + unsafe extern "C" fn( + *mut PyUFuncObject, + *mut *mut PyArray_Descr, + *mut PyArray_Descr, + *mut npy_intp, + npy_intp, + *mut PyUFunc_MaskedStridedInnerLoopFunc, + *mut *mut NpyAuxData, + *mut c_int, + ) -> c_int, +>; #[repr(C)] #[derive(Debug, Copy, Clone)] @@ -385,13 +384,10 @@ pub struct PyArrayMapIterObject { pub type NpyIter_IterNextFunc = Option c_int>; pub type NpyIter_GetMultiIndexFunc = Option; -pub type PyDataMem_EventHookFunc = Option; -pub type npy_iter_get_dataptr_t = Option *mut c_char>; +pub type PyDataMem_EventHookFunc = + Option; +pub type npy_iter_get_dataptr_t = + Option *mut c_char>; #[repr(C)] #[derive(Copy, Clone)] diff --git a/src/npyffi/types.rs b/src/npyffi/types.rs index ba5f94b77..31653e099 100644 --- a/src/npyffi/types.rs +++ b/src/npyffi/types.rs @@ -1,6 +1,6 @@ #![allow(non_camel_case_types)] -use pyffi::{Py_intptr_t, Py_uintptr_t, Py_hash_t}; +use pyo3::ffi::{Py_hash_t, Py_intptr_t, Py_uintptr_t}; use std::os::raw::*; pub type npy_intp = Py_intptr_t; diff --git a/src/npyffi/ufunc.rs b/src/npyffi/ufunc.rs index 6c0868c07..ba9c2f233 100644 --- a/src/npyffi/ufunc.rs +++ b/src/npyffi/ufunc.rs @@ -2,30 +2,30 @@ //! //! https://docs.scipy.org/doc/numpy/reference/c-api.ufunc.html +use std::ops::Deref; use std::os::raw::*; use std::ptr::null_mut; -use std::ops::Deref; -use pyffi; -use pyffi::{PyObject, PyTypeObject}; -use cpython::{Python, PythonObject, ObjectProtocol, PyResult, PyModule}; +use pyo3::ffi; +use pyo3::ffi::{PyObject, PyTypeObject}; +use pyo3::{ObjectProtocol, PyModule, PyResult, Python, ToPyPointer}; -use super::types::*; use super::objects::*; +use super::types::*; /// Low-Level binding for UFunc API /// https://docs.scipy.org/doc/numpy/reference/c-api.ufunc.html /// /// Most of UFunc API is exposed as the related function of this module object. -pub struct PyUFuncModule { - numpy: PyModule, +pub struct PyUFuncModule<'py> { + numpy: &'py PyModule, api: *const *const c_void, } -impl Deref for PyUFuncModule { +impl<'py> Deref for PyUFuncModule<'py> { type Target = PyModule; fn deref(&self) -> &Self::Target { - &self.numpy + self.numpy } } @@ -39,14 +39,13 @@ pub unsafe fn $fname(&self, $($arg : $t), *) $( -> $ret )* { } }} // pyufunc_api! -impl PyUFuncModule { +impl<'py> PyUFuncModule<'py> { /// Import `numpy.core.umath` to use UFunc API. - pub fn import(py: Python) -> PyResult { + pub fn import(py: Python<'py>) -> PyResult { let numpy = py.import("numpy.core.umath")?; - let c_api = numpy.as_object().getattr(py, "_UFUNC_API")?; + let c_api = numpy.getattr("_UFUNC_API")?; let api = unsafe { - pyffi::PyCapsule_GetPointer(c_api.as_object().as_ptr(), null_mut()) as - *const *const c_void + ffi::PyCapsule_GetPointer(c_api.as_ptr(), null_mut()) as *const *const c_void }; Ok(Self { numpy: numpy, diff --git a/src/types.rs b/src/types.rs index 9c7cd4fbf..d70a62cf1 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,10 +1,9 @@ - pub use num_complex::Complex32 as c32; pub use num_complex::Complex64 as c64; +pub use super::npyffi::npy_intp; pub use super::npyffi::NPY_ORDER; pub use super::npyffi::NPY_ORDER::{NPY_CORDER, NPY_FORTRANORDER}; -pub use super::npyffi::npy_intp; use super::npyffi::NPY_TYPES; @@ -17,12 +16,13 @@ pub trait TypeNum { macro_rules! impl_type_num { ($t:ty, $npy_t:ident) => { -impl TypeNum for $t { - fn typenum_enum() -> NPY_TYPES { - NPY_TYPES::$npy_t - } -} -}} // impl_type_num! + impl TypeNum for $t { + fn typenum_enum() -> NPY_TYPES { + NPY_TYPES::$npy_t + } + } + }; +} // impl_type_num! impl_type_num!(bool, NPY_BOOL); impl_type_num!(i32, NPY_INT); diff --git a/tests/array.rs b/tests/array.rs index c847f3d65..99e937eef 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1,14 +1,13 @@ - -extern crate cpython; -extern crate numpy; +extern crate pyo3; extern crate ndarray; +extern crate numpy; use ndarray::*; use numpy::*; #[test] fn new() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let n = 3; let m = 5; @@ -20,7 +19,7 @@ fn new() { #[test] fn zeros() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let n = 3; let m = 5; @@ -37,7 +36,7 @@ fn zeros() { #[test] fn arange() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let arr = PyArray::arange::(gil.python(), &np, 0.0, 1.0, 0.1); println!("ndim = {:?}", arr.ndim()); @@ -47,19 +46,21 @@ fn arange() { #[test] fn as_array() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let arr = PyArray::zeros::(gil.python(), &np, &[3, 2, 4], NPY_CORDER); let a = arr.as_array::().unwrap(); assert_eq!(arr.shape(), a.shape()); - assert_eq!(arr.strides().iter().map(|x| x / 8).collect::>(), - a.strides()); + assert_eq!( + arr.strides().iter().map(|x| x / 8).collect::>(), + a.strides() + ); } #[test] #[should_panic] fn as_array_panic() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let arr = PyArray::zeros::(gil.python(), &np, &[3, 2, 4], NPY_CORDER); let _a = arr.as_array::().unwrap(); @@ -67,7 +68,7 @@ fn as_array_panic() { #[test] fn into_pyarray_vec() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let a = vec![1, 2, 3]; @@ -79,7 +80,7 @@ fn into_pyarray_vec() { #[test] fn into_pyarray_array() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let a = Array3::::zeros((3, 4, 2)); @@ -96,7 +97,7 @@ fn into_pyarray_array() { #[test] fn iter_to_pyarray() { - let gil = cpython::Python::acquire_gil(); + let gil = pyo3::Python::acquire_gil(); let np = PyArrayModule::import(gil.python()).unwrap(); let arr = (0..10).map(|x| x * x).to_pyarray(gil.python(), &np); println!("arr.shape = {:?}", arr.shape());