The Cython docs discuss passing a pointer to a memoryview by using, e.g.:
cdef double[::1] x_view = x # some array
cdef double* ptr = &x_view[0]
however, when that array x has no elements (x.size == 0), trying to access x_view[0] fails. For the C library to which I am making an interface, passing a NULL pointer leads to a segfault, so I can't just check x.size and pass NULL.
Instead, I need to pass a pointer to a valid memory block of size 0. Using the old numpy array interface and passing <double*>x.data works even in the case of an empty array like x = np.array([]), but I am trying to move to using typed memoryviews with fused types to avoid code duplication and have more easily-enforceable type safety.
Is there an accepted way to handle this situation? Or are there plans for a feature like x_view.ptr that would handle this case internally?
1 Answer 1
I had to look this up in the Cython source to find it, but memoryviews do have an undocumented attribute _data and thus you can do
cdef double* ptr = <double*>x_view._data
(the cast is because the data attribute is just typed generically as char*).
With that said, I'm not completely sure I'd trust it for your purposes for a couple of reasons:
- Cython memoryviews just provide quick access into objects that provide the buffer protocol. It isn't clear to me from the buffer protocol docs if an object with 0-length has to provide a valid data pointer. i.e. I don't know if they're obliged to allocate memory for an empty array.
- If passing a
NULLpointer to your function fails, then that suggests your function is dereferencing the pointer itself (which is dubious for length-0 arrays).
To me that suggests you should do something like:
cdef double dummy_double
cdef double* ptr = &x_view[0] if x_view.shape[0] else &dummy_double
and then you know you're passing a pointer to some valid memory.
1 Comment
dummy_double option worked. It's an edge case since my interface gives an "empty" object output instead of raising an error for an empty array input, but I am making it consistent with a similar MATLAB code that does the same.