I am trying to wrap a C pointer array of type size_t
with a numpy ndarray
via Cython using the following:
cimport numpy as cnp
from libcpp.vector cimport vector
cnp.import_array()
cdef size_t num_layers = 10
cdef vector[size_t] steps_taken_vec = vector[size_t]()
steps_taken_vec.resize(3 * num_layers)
cdef size_t* steps_taken_ptr = steps_taken_vec.data()
cdef cnp.npy_intp[2] shape = [3, num_layers]
cdef cnp.npy_intp ndim = 2
self.shooting_method_steps_taken_array = cnp.PyArray_SimpleNewFromData(
ndim,
&shape[0],
cnp.NPY_UINTP, # <-- This is the problem
steps_taken_ptr) # steps_taken_ptr is a size_t*
The above produces the error "cimported module has no attribute 'NPY_UINTP'". According to numpy's documentation there should be an enum that directs numpy to create an array using size_t: https://numpy.org/devdocs/reference/c-api/dtype.html#c.NPY_TYPES.NPY_UINTP
The PyArray_SimpleNewFromData
API requires a enum that defines the type used to create the ndarray.
However, the actual init.pxd does not appear to have that enum. It does set the type correctly, see line 25 here but no enum in this list.
Those links, and my code, is using numpy 1.26.4. I looked ahead at 2.0+ and see that there was some definitional changes to this type, but the enum still appears to be missing (see here)
As a workaround, I am using cnp.NPY_UINT64
which works but I am not sure if that is guranteed to be the same size as size_t
across platforms and into the future.
Am I missing something here?
The easiest solution is probably to declare NPY_UINTP
yourself.
def extern from *:
cdef enum:
NPY_UINTP
This just assumes Cython that some enum-like constant exists called NPY_UINTP
. You can pass that to PyArray_SimpleNewFromData
. It doesn't matter that it's not from the "official" Numpy pxd file.
As I said in a comment, do report the missing constant to Numpy (or better yet, contribute a fix to Numpy). If they don't know then they can't fix it.