@@ -54,6 +54,18 @@ template <typename type, typename SFINAE = void>
5454struct npy_format_descriptor ;
5555
5656struct PyArrayDescr_Proxy {
57+ PyObject_HEAD
58+ PyObject *typeobj;
59+ char kind;
60+ char type;
61+ char byteorder;
62+ char _former_flags;
63+ int type_num;
64+ /* Additional fields are NumPy version specific. */
65+ };
66+
67+ /* NumPy 1 proxy (always includes legacy fields) */
68+ struct PyArrayDescr1_Proxy {
5769 PyObject_HEAD
5870 PyObject *typeobj;
5971 char kind;
@@ -68,6 +80,27 @@ struct PyArrayDescr_Proxy {
6880 PyObject *names;
6981};
7082
83+ /* NumPy 2 proxy, including legacy fields */
84+ struct PyArrayDescr2_Proxy {
85+ PyObject_HEAD
86+ PyObject *typeobj;
87+ char kind;
88+ char type;
89+ char byteorder;
90+ char _former_flags;
91+ int type_num;
92+ std::uint64_t flags;
93+ ssize_t elsize;
94+ ssize_t alignment;
95+ PyObject *metadata;
96+ Py_hash_t hash;
97+ void *reserved_null[2 ];
98+ /* The following fields only exist if 0 < type_num < 2000 */
99+ struct _arr_descr *subarray;
100+ PyObject *fields;
101+ PyObject *names;
102+ };
103+
71104struct PyArray_Proxy {
72105 PyObject_HEAD
73106 char *data;
@@ -203,6 +236,8 @@ struct npy_api {
203236 NPY_ULONG_, NPY_ULONGLONG_, NPY_UINT_),
204237 };
205238
239+ unsigned int PyArray_RUNTIME_VERSION_;
240+
206241 struct PyArray_Dims {
207242 Py_intptr_t *ptr;
208243 int len;
@@ -241,14 +276,6 @@ struct npy_api {
241276 PyObject *(*PyArray_FromAny_)(PyObject *, PyObject *, int , int , int , PyObject *);
242277 int (*PyArray_DescrConverter_)(PyObject *, PyObject **);
243278 bool (*PyArray_EquivTypes_)(PyObject *, PyObject *);
244- int (*PyArray_GetArrayParamsFromObject_)(PyObject *,
245- PyObject *,
246- unsigned char ,
247- PyObject **,
248- int *,
249- Py_intptr_t *,
250- PyObject **,
251- PyObject *);
252279 PyObject *(*PyArray_Squeeze_)(PyObject *);
253280 // Unused. Not removed because that affects ABI of the class.
254281 int (*PyArray_SetBaseObject_)(PyObject *, PyObject *);
@@ -275,7 +302,6 @@ struct npy_api {
275302 API_PyArray_View = 137 ,
276303 API_PyArray_DescrConverter = 174 ,
277304 API_PyArray_EquivTypes = 182 ,
278- API_PyArray_GetArrayParamsFromObject = 278 ,
279305 API_PyArray_SetBaseObject = 282
280306 };
281307
@@ -290,7 +316,8 @@ struct npy_api {
290316 npy_api api;
291317#define DECL_NPY_API (Func ) api.Func##_ = (decltype (api.Func##_)) api_ptr[API_##Func];
292318 DECL_NPY_API (PyArray_GetNDArrayCFeatureVersion);
293- if (api.PyArray_GetNDArrayCFeatureVersion_ () < 0x7 ) {
319+ api.PyArray_RUNTIME_VERSION_ = api.PyArray_GetNDArrayCFeatureVersion_ ();
320+ if (api.PyArray_RUNTIME_VERSION_ < 0x7 ) {
294321 pybind11_fail (" pybind11 numpy support requires numpy >= 1.7.0" );
295322 }
296323 DECL_NPY_API (PyArray_Type);
@@ -309,7 +336,6 @@ struct npy_api {
309336 DECL_NPY_API (PyArray_View);
310337 DECL_NPY_API (PyArray_DescrConverter);
311338 DECL_NPY_API (PyArray_EquivTypes);
312- DECL_NPY_API (PyArray_GetArrayParamsFromObject);
313339 DECL_NPY_API (PyArray_SetBaseObject);
314340
315341#undef DECL_NPY_API
@@ -331,6 +357,14 @@ inline const PyArrayDescr_Proxy *array_descriptor_proxy(const PyObject *ptr) {
331357 return reinterpret_cast <const PyArrayDescr_Proxy *>(ptr);
332358}
333359
360+ inline const PyArrayDescr1_Proxy *array_descriptor1_proxy (const PyObject *ptr) {
361+ return reinterpret_cast <const PyArrayDescr1_Proxy *>(ptr);
362+ }
363+
364+ inline const PyArrayDescr2_Proxy *array_descriptor2_proxy (const PyObject *ptr) {
365+ return reinterpret_cast <const PyArrayDescr2_Proxy *>(ptr);
366+ }
367+
334368inline bool check_flags (const void *ptr, int flag) {
335369 return (flag == (array_proxy (ptr)->flags & flag));
336370}
@@ -610,10 +644,23 @@ class dtype : public object {
610644 }
611645
612646 // / Size of the data type in bytes.
613- ssize_t itemsize () const { return detail::array_descriptor_proxy (m_ptr)->elsize ; }
647+ ssize_t itemsize () const {
648+ if (detail::npy_api::get ().PyArray_RUNTIME_VERSION_ < 0x12 ) {
649+ return detail::array_descriptor1_proxy (m_ptr)->elsize ;
650+ }
651+ return detail::array_descriptor2_proxy (m_ptr)->elsize ;
652+ }
614653
615654 // / Returns true for structured data types.
616- bool has_fields () const { return detail::array_descriptor_proxy (m_ptr)->names != nullptr ; }
655+ bool has_fields () const {
656+ if (detail::npy_api::get ().PyArray_RUNTIME_VERSION_ < 0x12 ) {
657+ return detail::array_descriptor1_proxy (m_ptr)->names != nullptr ;
658+ }
659+ if (num () < 0 || num () > 2000 ) {
660+ return false ;
661+ }
662+ return detail::array_descriptor2_proxy (m_ptr)->names != nullptr ;
663+ }
617664
618665 // / Single-character code for dtype's kind.
619666 // / For example, floating point types are 'f' and integral types are 'i'.
@@ -640,10 +687,20 @@ class dtype : public object {
640687 char byteorder () const { return detail::array_descriptor_proxy (m_ptr)->byteorder ; }
641688
642689 // / Alignment of the data type
643- int alignment () const { return detail::array_descriptor_proxy (m_ptr)->alignment ; }
690+ ssize_t alignment () const {
691+ if (detail::npy_api::get ().PyArray_RUNTIME_VERSION_ < 0x12 ) {
692+ return detail::array_descriptor1_proxy (m_ptr)->alignment ;
693+ }
694+ return detail::array_descriptor2_proxy (m_ptr)->alignment ;
695+ }
644696
645697 // / Flags for the array descriptor
646- char flags () const { return detail::array_descriptor_proxy (m_ptr)->flags ; }
698+ std::uint64_t flags () const {
699+ if (detail::npy_api::get ().PyArray_RUNTIME_VERSION_ < 0x12 ) {
700+ return (unsigned char ) detail::array_descriptor1_proxy (m_ptr)->flags ;
701+ }
702+ return detail::array_descriptor2_proxy (m_ptr)->flags ;
703+ }
647704
648705private:
649706 static object &_dtype_from_pep3118 () {
@@ -810,9 +867,7 @@ class array : public buffer {
810867 }
811868
812869 // / Byte size of a single element
813- ssize_t itemsize () const {
814- return detail::array_descriptor_proxy (detail::array_proxy (m_ptr)->descr )->elsize ;
815- }
870+ ssize_t itemsize () const { return dtype ().itemsize (); }
816871
817872 // / Total number of bytes
818873 ssize_t nbytes () const { return size () * itemsize (); }
0 commit comments