Как передать значение null во внешнюю библиотеку, используя ctypes, с аргументом, объявленным ctypeslib.ndpointer?
Вдохновленный другим answer здесь, у меня есть функция ctypes, которую я вызываю, используя ctypeslib.ndpointer
:
lib.foo.argtypes = [ctypeslib.ndpointer(np.complex64, ndim=1, flags='C'), POINTER(c_int)]
Внешняя функция объявляется следующим образом:
void foo(cmplx_float *array, int *length)
Моя проблема в том, что я хочу дважды вызвать эту функцию. В первый раз я хочу передать nullptr
в аргумент array
, чтобы я мог узнать нужную длину. Затем во второй раз я перейду в массив numpy.
Итак, я делаю так вот так:
lib.foo(None, length)
Это не выполняется со следующей ошибкой:
ctypes.ArgumentError: аргумент 1:: аргумент должен быть ndarray
Можно ли передать nullptr
?
Ответы
Ответ 1
Если (как и я) вы имеете дело с несколькими типами массивов, немного более удобное обходное решение - обернуть ndpointer
себя:
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')
Ответ 2
Следуя отличным советам eryksun в комментарии, я подклассифицировал тип, возвращаемый ctypeslib.ndpointer
, и реализовал переопределенный from_param
. Это немного сложно, так как это нужно сделать с помощью методов класса factory, потому что класс, возвращаемый ctypeslib.ndpointer
, выполняется с помощью factory.
Код, с которым я закончил:
_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)}
)
Большое спасибо eryksun за его (как всегда) совет экспертов.