@@ -53,17 +53,6 @@ struct handle_type_name<array> {
5353template <typename type, typename SFINAE = void >
5454struct npy_format_descriptor ;
5555
56- struct 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-
6756/* NumPy 1 proxy (always includes legacy fields) */
6857struct PyArrayDescr1_Proxy {
6958 PyObject_HEAD
@@ -80,6 +69,22 @@ struct PyArrayDescr1_Proxy {
8069 PyObject *names;
8170};
8271
72+ #ifdef PYBIND11_COMPILE_WITH_NUMPY2_SUPPORT
73+ struct PyArrayDescr_Proxy {
74+ PyObject_HEAD
75+ PyObject *typeobj;
76+ char kind;
77+ char type;
78+ char byteorder;
79+ char _former_flags;
80+ int type_num;
81+ /* Additional fields are NumPy version specific. */
82+ };
83+ #else
84+ /* NumPy 1.x only, we can expose all fields */
85+ typedef PyArrayDescr1_Proxy PyArrayDescr_Proxy;
86+ #endif
87+
8388/* NumPy 2 proxy, including legacy fields */
8489struct PyArrayDescr2_Proxy {
8590 PyObject_HEAD
@@ -164,6 +169,13 @@ PYBIND11_NOINLINE module_ import_numpy_core_submodule(const char *submodule_name
164169 object numpy_version = numpy_lib.attr (" NumpyVersion" )(version_string);
165170 int major_version = numpy_version.attr (" major" ).cast <int >();
166171
172+ #ifndef PYBIND11_COMPILE_WITH_NUMPY2_SUPPORT
173+ if (major_version >= 2 ) {
174+ throw std::runtime_error (" module compiled without NumPy 2 support. Please modify the "
175+ " `pybind11/numpy.h` include to `pybind11/numpy2.h` and recompile "
176+ " (this remains NumPy 1.x compatible but has minor changes)." );
177+ }
178+ #endif
167179 /* `numpy.core` was renamed to `numpy._core` in NumPy 2.0 as it officially
168180 became a private module. */
169181 std::string numpy_core_path = major_version >= 2 ? " numpy._core" : " numpy.core" ;
@@ -276,6 +288,16 @@ struct npy_api {
276288 PyObject *(*PyArray_FromAny_)(PyObject *, PyObject *, int , int , int , PyObject *);
277289 int (*PyArray_DescrConverter_)(PyObject *, PyObject **);
278290 bool (*PyArray_EquivTypes_)(PyObject *, PyObject *);
291+ #ifndef PYBIND11_COMPILE_WITH_NUMPY2_SUPPORT
292+ int (*PyArray_GetArrayParamsFromObject_)(PyObject *,
293+ PyObject *,
294+ unsigned char ,
295+ PyObject **,
296+ int *,
297+ Py_intptr_t *,
298+ PyObject **,
299+ PyObject *);
300+ #endif
279301 PyObject *(*PyArray_Squeeze_)(PyObject *);
280302 // Unused. Not removed because that affects ABI of the class.
281303 int (*PyArray_SetBaseObject_)(PyObject *, PyObject *);
@@ -302,6 +324,9 @@ struct npy_api {
302324 API_PyArray_View = 137 ,
303325 API_PyArray_DescrConverter = 174 ,
304326 API_PyArray_EquivTypes = 182 ,
327+ #ifndef PYBIND11_COMPILE_WITH_NUMPY2_SUPPORT
328+ API_PyArray_GetArrayParamsFromObject = 278 ,
329+ #endif
305330 API_PyArray_SetBaseObject = 282
306331 };
307332
@@ -644,12 +669,16 @@ class dtype : public object {
644669 }
645670
646671 // / Size of the data type in bytes.
672+ #ifndef PYBIND11_COMPILE_WITH_NUMPY2_SUPPORT
673+ int itemsize () const { return detail::array_descriptor_proxy (m_ptr)->elsize ; }
674+ #else
647675 ssize_t itemsize () const {
648676 if (detail::npy_api::get ().PyArray_RUNTIME_VERSION_ < 0x12 ) {
649677 return detail::array_descriptor1_proxy (m_ptr)->elsize ;
650678 }
651679 return detail::array_descriptor2_proxy (m_ptr)->elsize ;
652680 }
681+ #endif
653682
654683 // / Returns true for structured data types.
655684 bool has_fields () const {
@@ -686,21 +715,29 @@ class dtype : public object {
686715 // / Single character for byteorder
687716 char byteorder () const { return detail::array_descriptor_proxy (m_ptr)->byteorder ; }
688717
689- // / Alignment of the data type
718+ // / Alignment of the data type
719+ #ifndef PYBIND11_COMPILE_WITH_NUMPY2_SUPPORT
720+ int alignment () const { return detail::array_descriptor_proxy (m_ptr)->alignment ; }
721+ #else
690722 ssize_t alignment () const {
691723 if (detail::npy_api::get ().PyArray_RUNTIME_VERSION_ < 0x12 ) {
692- return detail::array_descriptor1_proxy (m_ptr)->alignment ;
724+ return detail::array_descriptor2_proxy (m_ptr)->alignment ;
693725 }
694- return detail::array_descriptor2_proxy (m_ptr)->alignment ;
726+ return detail::array_descriptor1_proxy (m_ptr)->alignment ;
695727 }
728+ #endif
696729
697- // / Flags for the array descriptor
730+ // / Flags for the array descriptor
731+ #ifndef PYBIND11_COMPILE_WITH_NUMPY2_SUPPORT
732+ char flags () const { return detail::array_descriptor_proxy (m_ptr)->flags ; }
733+ #else
698734 std::uint64_t flags () const {
699735 if (detail::npy_api::get ().PyArray_RUNTIME_VERSION_ < 0x12 ) {
700736 return (unsigned char ) detail::array_descriptor1_proxy (m_ptr)->flags ;
701737 }
702738 return detail::array_descriptor2_proxy (m_ptr)->flags ;
703739 }
740+ #endif
704741
705742private:
706743 static object &_dtype_from_pep3118 () {
0 commit comments