From 93993ee50ac0543d26577347446bd44c60e0a730 Mon Sep 17 00:00:00 2001 From: Alexis Duburcq Date: Fri, 15 Mar 2024 19:58:26 +0100 Subject: [PATCH 1/2] Add support of numpy 2.0.0b1 --- CHANGELOG.md | 1 + include/eigenpy/numpy-allocator.hpp | 8 ++++++++ include/eigenpy/numpy.hpp | 27 ++++++++++++++++++++++++++- include/eigenpy/user-type.hpp | 4 ++-- src/numpy.cpp | 6 +++++- src/register.cpp | 8 ++++---- 6 files changed, 46 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8edbc9dba..18791046b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Allow use of installed JRL-cmakemodule ([#446](https://github.com/stack-of-tasks/eigenpy/pull/446) +- Support of Numpy 2.0.0b1 ([#448](https://github.com/stack-of-tasks/eigenpy/pull/448)) ### Fixed - Fix unit test build in C++11 ([#442](https://github.com/stack-of-tasks/eigenpy/pull/442)) diff --git a/include/eigenpy/numpy-allocator.hpp b/include/eigenpy/numpy-allocator.hpp index 61653940a..c2c1ba798 100644 --- a/include/eigenpy/numpy-allocator.hpp +++ b/include/eigenpy/numpy-allocator.hpp @@ -138,7 +138,11 @@ struct numpy_allocator_impl_matrix > { outer_stride = reverse_strides ? mat.innerStride() : mat.outerStride(); +#if NPY_ABI_VERSION < 0x02000000 const int elsize = call_PyArray_DescrFromType(Scalar_type_code)->elsize; +#else + const int elsize = PyDataType_ELSIZE(call_PyArray_DescrFromType(Scalar_type_code)); +#endif npy_intp strides[2] = {elsize * inner_stride, elsize * outer_stride}; PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New( @@ -204,7 +208,11 @@ struct numpy_allocator_impl_matrix< outer_stride = reverse_strides ? mat.innerStride() : mat.outerStride(); +#if NPY_ABI_VERSION < 0x02000000 const int elsize = call_PyArray_DescrFromType(Scalar_type_code)->elsize; +#else + const int elsize = PyDataType_ELSIZE(call_PyArray_DescrFromType(Scalar_type_code)); +#endif npy_intp strides[2] = {elsize * inner_stride, elsize * outer_stride}; PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New( diff --git a/include/eigenpy/numpy.hpp b/include/eigenpy/numpy.hpp index 6ab627d8b..e1a4637f8 100644 --- a/include/eigenpy/numpy.hpp +++ b/include/eigenpy/numpy.hpp @@ -16,9 +16,34 @@ #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION #endif +/* Allow compiling against NumPy 1.x and 2.x + see: https://github.com/numpy/numpy/blob/afea8fd66f6bdbde855f5aff0b4e73eb0213c646/doc/source/reference/c-api/array.rst#L1224 +*/ +#if NPY_ABI_VERSION < 0x02000000 +#define PyArray_DescrProto PyArray_Descr +#endif + #include #include +#if NPY_ABI_VERSION < 0x02000000 + static inline PyArray_ArrFuncs * + PyDataType_GetArrFuncs(PyArray_Descr *descr) + { + return descr->f; + } +#endif + +/* PEP 674 disallow using macros as l-values + see : https://peps.python.org/pep-0674/ +*/ +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) +static inline void _Py_SET_TYPE(PyObject *o, PyTypeObject *type) { + Py_TYPE(o) = type; +} +#define Py_SET_TYPE(o, type) _Py_SET_TYPE((PyObject*)(o), type) +#endif + #if defined _WIN32 || defined __CYGWIN__ #define EIGENPY_GET_PY_ARRAY_TYPE(array) \ call_PyArray_MinScalarType(array)->type_num @@ -170,7 +195,7 @@ inline void call_PyArray_InitArrFuncs(PyArray_ArrFuncs* funcs) { PyArray_InitArrFuncs(funcs); } -inline int call_PyArray_RegisterDataType(PyArray_Descr* dtype) { +inline int call_PyArray_RegisterDataType(PyArray_DescrProto* dtype) { return PyArray_RegisterDataType(dtype); } diff --git a/include/eigenpy/user-type.hpp b/include/eigenpy/user-type.hpp index e66b2d9f5..b7eb67be6 100644 --- a/include/eigenpy/user-type.hpp +++ b/include/eigenpy/user-type.hpp @@ -171,7 +171,7 @@ struct SpecialMethods { char* srcptr = static_cast(src); PyArrayObject* py_array = static_cast(array); - PyArray_CopySwapFunc* copyswap = PyArray_DESCR(py_array)->f->copyswap; + PyArray_CopySwapFunc* copyswap = PyDataType_GetArrFuncs(PyArray_DESCR(py_array))->copyswap; for (npy_intp i = 0; i < n; i++) { copyswap(dstptr, srcptr, swap, array); @@ -189,7 +189,7 @@ struct SpecialMethods { return (npy_bool)(value != ZeroValue); } else { T tmp_value; - PyArray_DESCR(py_array)->f->copyswap( + PyDataType_GetArrFuncs(PyArray_DESCR(py_array))->copyswap( &tmp_value, ip, PyArray_ISBYTESWAPPED(py_array), array); return (npy_bool)(tmp_value != ZeroValue); } diff --git a/src/numpy.cpp b/src/numpy.cpp index 01018ba89..3b1a831e9 100644 --- a/src/numpy.cpp +++ b/src/numpy.cpp @@ -14,7 +14,11 @@ void import_numpy() { } int PyArray_TypeNum(PyTypeObject* type) { - return PyArray_TypeNumFromName(const_cast(type->tp_name)); + PyArray_Descr * descr = PyArray_DescrFromTypeObject(reinterpret_cast(type)); + if (descr == NULL) { + return NPY_NOTYPE; + } + return descr->type_num; } #if defined _WIN32 || defined __CYGWIN__ diff --git a/src/register.cpp b/src/register.cpp index 84e84f645..1a8ce771c 100644 --- a/src/register.cpp +++ b/src/register.cpp @@ -63,9 +63,9 @@ int Register::registerNewType( throw std::invalid_argument("PyType_Ready fails to initialize input type."); } - PyArray_Descr* descr_ptr = - new PyArray_Descr(*call_PyArray_DescrFromType(NPY_OBJECT)); - PyArray_Descr& descr = *descr_ptr; + PyArray_DescrProto* descr_ptr = new PyArray_DescrProto(); + Py_SET_TYPE(descr_ptr, &PyArrayDescr_Type); + PyArray_DescrProto& descr = *descr_ptr; descr.typeobj = py_type_ptr; descr.kind = 'V'; descr.byteorder = '='; @@ -98,7 +98,7 @@ int Register::registerNewType( PyArray_Descr* new_descr = call_PyArray_DescrFromType(code); if (PyDict_SetItemString(py_type_ptr->tp_dict, "dtype", - (PyObject*)descr_ptr) < 0) { + (PyObject*)new_descr) < 0) { throw std::invalid_argument("PyDict_SetItemString fails."); } From 98717f00aa6ad128c3157cdc53f8b5b43036fce2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 15 Mar 2024 20:25:18 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- include/eigenpy/numpy-allocator.hpp | 6 ++++-- include/eigenpy/numpy.hpp | 13 ++++++------- include/eigenpy/user-type.hpp | 7 ++++--- src/numpy.cpp | 5 +++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/include/eigenpy/numpy-allocator.hpp b/include/eigenpy/numpy-allocator.hpp index c2c1ba798..4dd5f7e09 100644 --- a/include/eigenpy/numpy-allocator.hpp +++ b/include/eigenpy/numpy-allocator.hpp @@ -141,7 +141,8 @@ struct numpy_allocator_impl_matrix > { #if NPY_ABI_VERSION < 0x02000000 const int elsize = call_PyArray_DescrFromType(Scalar_type_code)->elsize; #else - const int elsize = PyDataType_ELSIZE(call_PyArray_DescrFromType(Scalar_type_code)); + const int elsize = + PyDataType_ELSIZE(call_PyArray_DescrFromType(Scalar_type_code)); #endif npy_intp strides[2] = {elsize * inner_stride, elsize * outer_stride}; @@ -211,7 +212,8 @@ struct numpy_allocator_impl_matrix< #if NPY_ABI_VERSION < 0x02000000 const int elsize = call_PyArray_DescrFromType(Scalar_type_code)->elsize; #else - const int elsize = PyDataType_ELSIZE(call_PyArray_DescrFromType(Scalar_type_code)); + const int elsize = + PyDataType_ELSIZE(call_PyArray_DescrFromType(Scalar_type_code)); #endif npy_intp strides[2] = {elsize * inner_stride, elsize * outer_stride}; diff --git a/include/eigenpy/numpy.hpp b/include/eigenpy/numpy.hpp index e1a4637f8..3529ec257 100644 --- a/include/eigenpy/numpy.hpp +++ b/include/eigenpy/numpy.hpp @@ -17,7 +17,8 @@ #endif /* Allow compiling against NumPy 1.x and 2.x - see: https://github.com/numpy/numpy/blob/afea8fd66f6bdbde855f5aff0b4e73eb0213c646/doc/source/reference/c-api/array.rst#L1224 + see: + https://github.com/numpy/numpy/blob/afea8fd66f6bdbde855f5aff0b4e73eb0213c646/doc/source/reference/c-api/array.rst#L1224 */ #if NPY_ABI_VERSION < 0x02000000 #define PyArray_DescrProto PyArray_Descr @@ -27,18 +28,16 @@ #include #if NPY_ABI_VERSION < 0x02000000 - static inline PyArray_ArrFuncs * - PyDataType_GetArrFuncs(PyArray_Descr *descr) - { - return descr->f; - } +static inline PyArray_ArrFuncs* PyDataType_GetArrFuncs(PyArray_Descr* descr) { + return descr->f; +} #endif /* PEP 674 disallow using macros as l-values see : https://peps.python.org/pep-0674/ */ #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) -static inline void _Py_SET_TYPE(PyObject *o, PyTypeObject *type) { +static inline void _Py_SET_TYPE(PyObject* o, PyTypeObject* type) { Py_TYPE(o) = type; } #define Py_SET_TYPE(o, type) _Py_SET_TYPE((PyObject*)(o), type) diff --git a/include/eigenpy/user-type.hpp b/include/eigenpy/user-type.hpp index b7eb67be6..bcca55542 100644 --- a/include/eigenpy/user-type.hpp +++ b/include/eigenpy/user-type.hpp @@ -171,7 +171,8 @@ struct SpecialMethods { char* srcptr = static_cast(src); PyArrayObject* py_array = static_cast(array); - PyArray_CopySwapFunc* copyswap = PyDataType_GetArrFuncs(PyArray_DESCR(py_array))->copyswap; + PyArray_CopySwapFunc* copyswap = + PyDataType_GetArrFuncs(PyArray_DESCR(py_array))->copyswap; for (npy_intp i = 0; i < n; i++) { copyswap(dstptr, srcptr, swap, array); @@ -189,8 +190,8 @@ struct SpecialMethods { return (npy_bool)(value != ZeroValue); } else { T tmp_value; - PyDataType_GetArrFuncs(PyArray_DESCR(py_array))->copyswap( - &tmp_value, ip, PyArray_ISBYTESWAPPED(py_array), array); + PyDataType_GetArrFuncs(PyArray_DESCR(py_array)) + ->copyswap(&tmp_value, ip, PyArray_ISBYTESWAPPED(py_array), array); return (npy_bool)(tmp_value != ZeroValue); } } diff --git a/src/numpy.cpp b/src/numpy.cpp index 3b1a831e9..e758ed02d 100644 --- a/src/numpy.cpp +++ b/src/numpy.cpp @@ -14,9 +14,10 @@ void import_numpy() { } int PyArray_TypeNum(PyTypeObject* type) { - PyArray_Descr * descr = PyArray_DescrFromTypeObject(reinterpret_cast(type)); + PyArray_Descr* descr = + PyArray_DescrFromTypeObject(reinterpret_cast(type)); if (descr == NULL) { - return NPY_NOTYPE; + return NPY_NOTYPE; } return descr->type_num; }