Inspired by another answer here, I have a ctypes function that I am calling using ctypeslib.ndpointer
:
lib.foo.argtypes = [ctypeslib.ndpointer(np.complex64, ndim=1, flags='C'), POINTER(c_int)]
The external function is declared like so:
void foo(cmplx_float *array, int *length)
My problem is that I want to call the function twice. The first time I want to pass nullptr
to the array
argument, so that I can find out the required length. Then the second time, I will pass in a numpy array.
So I do so like this:
lib.foo(None, length)
This fails with the following error:
ctypes.ArgumentError: argument 1: : argument must be an ndarray
Is it possible for me to pass nullptr
?
If (like me) you are dealing with multiple different array types, a slightly nicer workaround is to wrap ndpointer
itself:
import numpy as np
from numpy.ctypeslib import ndpointer
def wrapped_ndptr(*args, **kwargs):
base = ndpointer(*args, **kwargs)
def from_param(cls, obj):
if obj is None:
return obj
return base.from_param(obj)
return type(base.__name__, (base,), {'from_param': classmethod(from_param)})
ComplexArrayType = wrapped_ndptr(dtype=np.complex128, ndim=1, flags='C_CONTIGUOUS')
DoubleArrayType = wrapped_ndptr(dtype=np.float64, ndim=1, flags='C_CONTIGUOUS')
Following the excellent advice from eryksun in a comment I subclassed the type returned by ctypeslib.ndpointer
and implemented an overridden from_param
. This is a little tricky as it has to be done using class factory techniques, because the class returned by ctypeslib.ndpointer
is made by a factory.
The code that I ended up with:
_ComplexArrayTypeBase = numpy.ctypeslib.ndpointer(dtype=numpy.complex128, ndim=1,
flags='C_CONTIGUOUS')
def _from_param(cls, obj):
if obj is None:
return obj
return _ComplexArrayTypeBase.from_param(obj)
ComplexArrayType = type(
'ComplexArrayType',
(_ComplexArrayTypeBase,),
{'from_param': classmethod(_from_param)}
)
Many thanks to eryksun for his (as always) expert advice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With