[python / cpprb] Failed to build cpprb error: ‘PyArray_Descr’ {aka ‘struct _PyArray_Descr’} has no member named ‘subarray’ というエラーの対処法

# 概要

`python` のライブラリである `cpprb` というものをインストールしようとしたところ、以下のようなエラーが発生した。

- Failed to build cpprb error: ‘PyArray_Descr’ {aka ‘struct _PyArray_Descr’} has no member named ‘subarray’

この解決策を記載したのがこの記事である。

# 動作環境

item|version など
--|--
OS|Ubuntu
docker image|python:3.12.10-slim
python|3.10.12
numpy|1.26.4
cpprb|10.7.2

# 解決策

`cpprb` のバージョンを `11.0.0` にし、念の為 `numpy` のバージョンを `2.0.0` にしたところ、解決した。。。
こんな解決方法でいいのか...という感じはするが、どこかの誰かの役に立てば嬉しい( \*¯ ꒳¯\*)✨


# 発生したエラー

参考までに、発生したエラーを掲載しておく。

```rust
#0 404.9   Building wheel for cpprb (pyproject.toml): started
#0 406.4   Building wheel for cpprb (pyproject.toml): finished with status 'error'
#0 406.4   error: subprocess-exited-with-error
#0 406.4   
#0 406.4   × Building wheel for cpprb (pyproject.toml) did not run successfully.
#0 406.4   │ exit code: 1
#0 406.4   ╰─> [73 lines of output]
#0 406.4       <string>:122: UserWarning: No README.md
#0 406.4       /tmp/pip-build-env-b7te_42x/overlay/lib/python3.12/site-packages/setuptools/dist.py:759: SetuptoolsDeprecationWarning: License classifiers are deprecated.
#0 406.4       !!
#0 406.4       
#0 406.4               ********************************************************************************
#0 406.4               Please consider removing the following classifiers in favor of a SPDX license expression:
#0 406.4       
#0 406.4               License :: OSI Approved :: MIT License
#0 406.4       
#0 406.4               See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details.
#0 406.4               ********************************************************************************
#0 406.4       
#0 406.4       !!
#0 406.4         self._finalize_license_expression()
#0 406.4       running bdist_wheel
#0 406.4       running build
#0 406.4       running build_py
#0 406.4       creating build/lib.linux-aarch64-cpython-312/cpprb
#0 406.4       copying cpprb/HER.py -> build/lib.linux-aarch64-cpython-312/cpprb
#0 406.4       copying cpprb/LaBER.py -> build/lib.linux-aarch64-cpython-312/cpprb
#0 406.4       copying cpprb/__init__.py -> build/lib.linux-aarch64-cpython-312/cpprb
#0 406.4       copying cpprb/util.py -> build/lib.linux-aarch64-cpython-312/cpprb
#0 406.4       copying cpprb/multiprocessing.py -> build/lib.linux-aarch64-cpython-312/cpprb
#0 406.4       running build_ext
#0 406.4       building 'cpprb.PyReplayBuffer' extension
#0 406.4       creating build/temp.linux-aarch64-cpython-312/cpprb
#0 406.4       g++ -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O3 -Wall -fPIC -Icpprb -I/usr/local/include/python3.12 -I/tmp/pip-build-env-b7te_42x/normal/lib/python3.12/site-packages/numpy/_core/include -c cpprb/PyReplayBuffer.cpp -o build/temp.linux-aarch64-cpython-312/cpprb/PyReplayBuffer.o -std=c++17 -march=native
#0 406.4       In file included from /tmp/pip-build-env-b7te_42x/normal/lib/python3.12/site-packages/numpy/_core/include/numpy/ndarraytypes.h:1913,
#0 406.4                        from /tmp/pip-build-env-b7te_42x/normal/lib/python3.12/site-packages/numpy/_core/include/numpy/ndarrayobject.h:12,
#0 406.4                        from /tmp/pip-build-env-b7te_42x/normal/lib/python3.12/site-packages/numpy/_core/include/numpy/arrayobject.h:5,
#0 406.4                        from cpprb/PyReplayBuffer.cpp:1219:
#0 406.4       /tmp/pip-build-env-b7te_42x/normal/lib/python3.12/site-packages/numpy/_core/include/numpy/npy_1_7_deprecated_api.h:17:2: warning: #warning "Using deprecated NumPy API, disable it with " "#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-Wcpp]
#0 406.4          17 | #warning "Using deprecated NumPy API, disable it with " \
#0 406.4             |  ^~~~~~~
#0 406.4       In file included from /usr/local/include/python3.12/Python.h:38,
#0 406.4                        from cpprb/PyReplayBuffer.cpp:42:
#0 406.4       cpprb/PyReplayBuffer.cpp: In function ‘PyObject* __pyx_f_5numpy_PyDataType_SHAPE(PyArray_Descr*)’:
#0 406.4       cpprb/PyReplayBuffer.cpp:23400:41: error: ‘PyArray_Descr’ {aka ‘struct _PyArray_Descr’} has no member named ‘subarray’
#0 406.4       23400 |     __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape));
#0 406.4             |                                         ^~~~~~~~
#0 406.4       /usr/local/include/python3.12/pyport.h:24:38: note: in definition of macro ‘_Py_CAST’
#0 406.4          24 | #define _Py_CAST(type, expr) ((type)(expr))
#0 406.4             |                                      ^~~~
#0 406.4       /usr/local/include/python3.12/object.h:661:35: note: in expansion of macro ‘_PyObject_CAST’
#0 406.4         661 | #  define Py_INCREF(op) Py_INCREF(_PyObject_CAST(op))
#0 406.4             |                                   ^~~~~~~~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp:2819:27: note: in expansion of macro ‘Py_INCREF’
#0 406.4        2819 |   #define __Pyx_INCREF(r) Py_INCREF(r)
#0 406.4             |                           ^~~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp:23400:5: note: in expansion of macro ‘__Pyx_INCREF’
#0 406.4       23400 |     __Pyx_INCREF(((PyObject*)__pyx_v_d->subarray->shape));
#0 406.4             |     ^~~~~~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp:23401:38: error: ‘PyArray_Descr’ {aka ‘struct _PyArray_Descr’} has no member named ‘subarray’
#0 406.4       23401 |     __pyx_r = ((PyObject*)__pyx_v_d->subarray->shape);
#0 406.4             |                                      ^~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp: In function ‘PyObject* __pyx_pf_5cpprb_14PyReplayBuffer_11NstepBuffer_4add(__pyx_obj_5cpprb_14PyReplayBuffer_NstepBuffer*, PyObject*)’:
#0 406.4       cpprb/PyReplayBuffer.cpp:35485:28: warning: comparison of integer expressions of different signedness: ‘Py_ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
#0 406.4       35485 |   __pyx_t_2 = (__pyx_v_end <= __pyx_v_self->buffer_size);
#0 406.4             |                ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp:36507:41: warning: comparison of integer expressions of different signedness: ‘Py_ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
#0 406.4       36507 |         __pyx_t_2 = (__pyx_v_stored_end <= __pyx_v_self->buffer_size);
#0 406.4             |                      ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp:36958:35: warning: comparison of integer expressions of different signedness: ‘Py_ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
#0 406.4       36958 |   for (__pyx_t_16 = 1; __pyx_t_16 < __pyx_t_14; __pyx_t_16+=1) {
#0 406.4             |                        ~~~~~~~~~~~^~~~~~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp:36969:28: warning: comparison of integer expressions of different signedness: ‘Py_ssize_t’ {aka ‘long int’} and ‘size_t’ {aka ‘long unsigned int’} [-Wsign-compare]
#0 406.4       36969 |     __pyx_t_2 = (__pyx_v_i <= __pyx_v_add_N);
#0 406.4             |                  ~~~~~~~~~~^~~~~~~~~~~~~~~~
#0 406.4       cpprb/PyReplayBuffer.cpp: In function ‘PyObject* __pyx_pf_5cpprb_14PyReplayBuffer_19ReverseReplayBuffer_4sample(__pyx_obj_5cpprb_14PyReplayBuffer_ReverseReplayBuffer*, PyObject*)’:
#0 406.4       cpprb/PyReplayBuffer.cpp:53939:33: warning: comparison of integer expressions of different signedness: ‘size_t’ {aka ‘long unsigned int’} and ‘long int’ [-Wsign-compare]
#0 406.4       53939 |   for (__pyx_t_1 = 0; __pyx_t_1 < __pyx_t_9; __pyx_t_1+=1) {
#0 406.4             |                       ~~~~~~~~~~^~~~~~~~~~~
#0 406.4       error: command '/usr/bin/g++' failed with exit code 1
#0 406.4       [end of output]
#0 406.4   
#0 406.4   note: This error originates from a subprocess, and is likely not a problem with pip.
#0 406.4   ERROR: Failed building wheel for cpprb
#0 406.4   Building wheel for pybullet (pyproject.toml): started
#0 467.7   Building wheel for pybullet (pyproject.toml): still running...
#0 490.5   Building wheel for pybullet (pyproject.toml): finished with status 'done'
#0 490.6   Created wheel for pybullet: filename=pybullet-3.2.6-cp312-cp312-linux_aarch64.whl size=100944774 sha256=7d52d603957fbfa4e3a1f11622ffdb8608366f2220cf26c4cc6b0c52b4d30e7f
#0 490.6   Stored in directory: /root/.cache/pip/wheels/d2/82/a7/86fd408fe12eb6a27cfa8328e42c86630a465baa60b43ba3a6
#0 490.6   Building wheel for JSAnimation (pyproject.toml): started
#0 490.8   Building wheel for JSAnimation (pyproject.toml): finished with status 'done'
#0 490.8   Created wheel for JSAnimation: filename=jsanimation-0.1-py3-none-any.whl size=11463 sha256=6b8e8dc702ec0c6e17a12b35628ffeb06bd52f93e3efe4384bde5abc96e7a905
#0 490.8   Stored in directory: /root/.cache/pip/wheels/2d/6e/2e/c0e2a000cd36fbb86a92b6e7f0042a195ca3a080898a928f9f
#0 490.8   Building wheel for box2d-py (pyproject.toml): started
#0 515.1   Building wheel for box2d-py (pyproject.toml): finished with status 'done'
#0 515.1   Created wheel for box2d-py: filename=box2d_py-2.3.5-cp312-cp312-linux_aarch64.whl size=2491908 sha256=1aca257617f697372eaff81ccac3159fd6409a5ae37ec423cb5728982a7a1765
#0 515.1   Stored in directory: /root/.cache/pip/wheels/2a/e9/60/774da0bcd07f7dc7761a8590fa2d065e4069568e78dcdc3318
#0 515.1   Building wheel for gym (pyproject.toml): started
#0 515.4   Building wheel for gym (pyproject.toml): finished with status 'done'
#0 515.4   Created wheel for gym: filename=gym-0.26.2-py3-none-any.whl size=827727 sha256=c27e24851e72aa4de3e09b20e8946d8af804cb3c5e7f66c708cbcd5c7a471cd0
#0 515.4   Stored in directory: /root/.cache/pip/wheels/95/51/6c/9bb05ebbe7c5cb8171dfaa3611f32622ca4658d53f31c79077
#0 515.4 Successfully built scikit-learn pybullet JSAnimation box2d-py gym
#0 515.4 Failed to build cpprb
#0 515.4 ERROR: Failed to build installable wheels for some pyproject.toml based projects (cpprb)
------
failed to solve: executor failed running [/bin/sh -c pip install -r requirements.txt]: exit code: 1
```


# 関連記事

numpy のバージョンを上げたのは、この GitHub issue のコメントの方にバージョンを合わせるため。

https://github.com/cython/cython/issues/6249#issuecomment-2176913963

ただ、本当に numpy のバージョン変更が本当必要だったのかどうかはわからない。