如何使用ctypes将NumPy复杂数组与C函数连接?

maj*_*588 4 c python ctypes numpy

我在C中有一个函数,它接受一系列复杂的浮点数并对它们进行就地计算:

/* foo.c */
void foo(cmplx_float* array, int length) {...}
Run Code Online (Sandbox Code Playgroud)

复杂的float结构如下所示:

typedef struct cmplx_float {
   float real;
   float imag;
} cmplx_float ;
Run Code Online (Sandbox Code Playgroud)

我需要使用ctypes在python中调用该函数.在Python中,我有一个复杂64元素的Numpy 1-D ndarray.

我还创建了一个派生自ctypes的类.结构:

class c_float(Structure):
   _fields_ = [('real', c_float),
               ('imag', c_float)]
Run Code Online (Sandbox Code Playgroud)

我想我可能需要另一个实现结构数组的python类.总的来说,我只是将这些碎片连接在一起时遇到了问题.最终需要做什么才能在Python中调用我的函数,或多或少是这样的:

some_ctype_array = SomeConversionCode(cmplx_numpy_array) 
lib.foo(some_ctype_array, length)
Run Code Online (Sandbox Code Playgroud)

War*_*ser 7

您可以使用ndpointerfrom numpy.ctypeslib来声明第一个参数是一维连续的数组类型numpy.complex64:

import numpy as np
from numpy import ctypeslib

# ...code to load the shared library as `lib` not shown...

# Declare the argument types of lib.foo:
lib.foo.argtypes = [ctypeslib.ndpointer(np.complex64, ndim=1, flags='C'), c_int]
Run Code Online (Sandbox Code Playgroud)

然后,你可以这样做,例如,

z = np.array([1+2j, -3+4j, 5.0j], dtype=np.complex64)
lib.foo(z, z.size)
Run Code Online (Sandbox Code Playgroud)

您可能希望将其包装在不需要第二个参数的函数中:

def foo(z):
    # Ensure that we use a contiguous array of complex64.  If the
    # call to foo(z, z.size) modifies z in place, and that is the
    # intended effect of the function, then the following line should
    # be removed. (The input z is then *required* to be a contiguous 
    # array of np.complex64.) 
    z = np.ascontiguousarray(z, dtype=np.complex64)
    # Call the C function.
    lib.foo(z, z.size)
Run Code Online (Sandbox Code Playgroud)