From 48b4a8430111d7fdd16e0747921a9af9c0069842 Mon Sep 17 00:00:00 2001 From: Pim Schellart Date: Mon, 17 Jul 2017 18:05:32 -0400 Subject: [PATCH] Use NumPy 1.7 API for pybind11 --- include/ndarray/converter/eigen.h | 11 +++---- include/ndarray/converter/numpy.h | 42 +++++++++++++++------------ include/ndarray/converter/ufunctors.h | 14 ++++----- tests/pybind11_test_mod.cc | 1 + 4 files changed, 38 insertions(+), 30 deletions(-) diff --git a/include/ndarray/converter/eigen.h b/include/ndarray/converter/eigen.h index 401b4362..30895fc6 100644 --- a/include/ndarray/converter/eigen.h +++ b/include/ndarray/converter/eigen.h @@ -30,6 +30,7 @@ template struct PyConverter< EigenView > { static bool fromPythonStage1(PyPtr & p) { + auto array = reinterpret_cast(p.get()); // add or remove dimensions with size one so we have the right number of dimensions if (PyArray_Check(p.get())) { if ((Rows_ == 1 || Cols_ == 1) && N == 2) { @@ -40,11 +41,11 @@ struct PyConverter< EigenView > { shape[1] = 1; } PyArray_Dims dims = { shape, 2 }; - PyPtr r(PyArray_Newshape(reinterpret_cast(p.get()), &dims, NPY_ANYORDER)); + PyPtr r(PyArray_Newshape(array, &dims, NPY_ANYORDER)); if (!r) return false; p.swap(r); } else if (N == 1) { - PyPtr r(PyArray_Squeeze(reinterpret_cast(p.get()))); + PyPtr r(PyArray_Squeeze(array)); if (!r) return false; p.swap(r); } @@ -52,17 +53,17 @@ struct PyConverter< EigenView > { if (!PyConverter< Array >::fromPythonStage1(p)) return false; // check whether the size is correct if it's static if (N == 2) { - if (Rows_ != Eigen::Dynamic && PyArray_DIM(p.get(), 0) != Rows_) { + if (Rows_ != Eigen::Dynamic && PyArray_DIM(array, 0) != Rows_) { PyErr_SetString(PyExc_ValueError, "incorrect number of rows for matrix"); return false; } - if (Cols_ != Eigen::Dynamic && PyArray_DIM(p.get(), 1) != Cols_) { + if (Cols_ != Eigen::Dynamic && PyArray_DIM(array, 1) != Cols_) { PyErr_SetString(PyExc_ValueError, "incorrect number of columns for matrix"); return false; } } else { int requiredSize = Rows_ * Cols_; - if (requiredSize != Eigen::Dynamic && PyArray_SIZE(p.get()) != requiredSize) { + if (requiredSize != Eigen::Dynamic && PyArray_SIZE(array) != requiredSize) { PyErr_SetString(PyExc_ValueError, "incorrect number of elements for vector"); return false; } diff --git a/include/ndarray/converter/numpy.h b/include/ndarray/converter/numpy.h index e71b36f8..9b887819 100644 --- a/include/ndarray/converter/numpy.h +++ b/include/ndarray/converter/numpy.h @@ -11,6 +11,10 @@ #ifndef NDARRAY_CONVERTER_numpy_h_INCLUDED #define NDARRAY_CONVERTER_numpy_h_INCLUDED +#ifndef NPY_NO_DEPRECATED_API +#pragma message ( "ndarray is compatible with the NumPy 1.7 API, define NPY_NO_DEPRECATED_API to suppress API version warnings" ) +#endif + /** * @file ndarray/converter/numpy.h * @brief Python C-API conversions between ndarray and numpy. @@ -155,25 +159,26 @@ struct PyConverter< Array > : public detail::PyConverterBase< Array(p.get()); + int actualType = PyArray_TYPE(array); int requiredType = detail::NumpyTraits::getCode(); if (actualType != requiredType) { PyErr_SetString(PyExc_ValueError, ("numpy.ndarray argument has incorrect data type")); return false; } - if (PyArray_NDIM(p.get()) != N) { + if (PyArray_NDIM(array) != N) { PyErr_SetString(PyExc_ValueError, "numpy.ndarray argument has incorrect number of dimensions"); return false; } bool writeable = !boost::is_const::value; - if (writeable && !(PyArray_FLAGS(p.get()) & NPY_WRITEABLE)) { + if (writeable && !(PyArray_FLAGS(array) & NPY_ARRAY_WRITEABLE)) { PyErr_SetString(PyExc_TypeError, "numpy.ndarray argument must be writeable"); return false; } if (C > 0) { Offset requiredStride = sizeof(Element); for (int i = 0; i < C; ++i) { - Offset actualStride = PyArray_STRIDE(p.get(), N-i-1); + Offset actualStride = PyArray_STRIDE(array, N-i-1); if (actualStride != requiredStride) { PyErr_SetString( PyExc_ValueError, @@ -181,12 +186,12 @@ struct PyConverter< Array > : public detail::PyConverterBase< Array > : public detail::PyConverterBase< Array > : public detail::PyConverterBase< Array & output ///< Reference to existing output C++ object. ) { - if (!(PyArray_FLAGS(input.get()) & NPY_ALIGNED)) { + auto array = reinterpret_cast(input.get()); + if (!(PyArray_FLAGS(array) & NPY_ARRAY_ALIGNED)) { PyErr_SetString(PyExc_TypeError, "unaligned arrays cannot be converted to C++"); return false; } Offset itemsize = sizeof(Element); for (int i = 0; i < N; ++i) { - if ((PyArray_DIM(input.get(), i) > 1) && (PyArray_STRIDE(input.get(), i) % itemsize != 0)) { + if ((PyArray_DIM(array, i) > 1) && (PyArray_STRIDE(array, i) % itemsize != 0)) { PyErr_SetString( PyExc_TypeError, "Cannot convert array to C++: strides must be an integer multiple of the element size" @@ -232,11 +238,11 @@ struct PyConverter< Array > : public detail::PyConverterBase< Array shape; Vector strides; - std::copy(PyArray_DIMS(input.get()), PyArray_DIMS(input.get()) + N, shape.begin()); - std::copy(PyArray_STRIDES(input.get()), PyArray_STRIDES(input.get()) + N , strides.begin()); + std::copy(PyArray_DIMS(array), PyArray_DIMS(array) + N, shape.begin()); + std::copy(PyArray_STRIDES(array), PyArray_STRIDES(array) + N , strides.begin()); for (int i = 0; i < N; ++i) strides[i] /= sizeof(Element); output = external( - reinterpret_cast(PyArray_DATA(input.get())), + reinterpret_cast(PyArray_DATA(array)), shape, strides, input ); return true; @@ -257,10 +263,10 @@ struct PyConverter< Array > : public detail::PyConverterBase< Array::value; - if (writeable) flags |= NPY_WRITEABLE; + if (writeable) flags |= NPY_ARRAY_WRITEABLE; npy_intp outShape[N]; npy_intp outStrides[N]; Vector inShape = m.getShape(); @@ -276,8 +282,8 @@ struct PyConverter< Array > : public detail::PyConverterBase< Array > : public detail::PyConverterBase< Array(array.get())->base = owner; + PyArray_SetBaseObject(reinterpret_cast(array.get()), owner); } Py_INCREF(array.get()); return PyArray_Return(reinterpret_cast(array.get())); diff --git a/include/ndarray/converter/ufunctors.h b/include/ndarray/converter/ufunctors.h index 9d8f1e19..c65b0e53 100644 --- a/include/ndarray/converter/ufunctors.h +++ b/include/ndarray/converter/ufunctors.h @@ -26,17 +26,17 @@ template ::getCode(), - NPY_ALIGNED); + PyArrayObject* input_array = PyArray_FROM_OTF(input,detail::NumpyTraits::getCode(), + NPY_ARRAY_ALIGNED); if (input_array == NULL) return NULL; - PyObject* output_array; + PyArrayObject* output_array; if (output == NULL || output == Py_None) { output_array = PyArray_SimpleNew(PyArray_NDIM(input_array), PyArray_DIMS(input_array), detail::NumpyTraits::getCode()); } else { output_array = PyArray_FROM_OTF(output,detail::NumpyTraits::getCode(), - NPY_ALIGNED | NPY_WRITEABLE | NPY_UPDATEIFCOPY); + NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE | NPY_ARRAY_UPDATEIFCOPY); } if (output_array == NULL) { Py_DECREF(input_array); @@ -72,9 +72,9 @@ struct PyBinaryUFunctor { static PyObject* _call_(TBinaryFunctor const& self, PyObject* input1, PyObject* input2, PyObject* output) { PyObject* input1_array = PyArray_FROM_OTF(input1,detail::NumpyTraits::getCode(), - NPY_ALIGNED); + NPY_ARRAY_ALIGNED); PyObject* input2_array = PyArray_FROM_OTF(input2,detail::NumpyTraits::getCode(), - NPY_ALIGNED); + NPY_ARRAY_ALIGNED); if (input1_array == NULL || input2_array == NULL) { Py_XDECREF(input1_array); Py_XDECREF(input2_array); @@ -94,7 +94,7 @@ struct PyBinaryUFunctor { Py_DECREF(tmp); } else { output_array = PyArray_FROM_OTF(output,detail::NumpyTraits::getCode(), - NPY_ALIGNED | NPY_WRITEABLE | NPY_UPDATEIFCOPY); + NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE | NPY_ARRAY_UPDATEIFCOPY); } if (output_array == NULL) { Py_DECREF(input1_array); diff --git a/tests/pybind11_test_mod.cc b/tests/pybind11_test_mod.cc index 22118c2e..5e75def6 100644 --- a/tests/pybind11_test_mod.cc +++ b/tests/pybind11_test_mod.cc @@ -1,3 +1,4 @@ +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #include "pybind11/pybind11.h" #include "numpy/arrayobject.h"