如何在 Python 中使用具有复杂类型的 C 函数?

How to use a C function with complex types in Python?

我决定将我的一些 Python 函数移植到 C,主要是遵循 this simple tutorial. Problem is that my C function returns a complex float, and there's no corresponding type in ctypes's documentation。这是我对跨语言编码和 C 的有限知识无法解决的问题,甚至扩展了 Google。

我的 C 函数是这样工作的:

#include <tgmath.h>
float _Complex integrand(float _Complex theta1, double r, double z){
    //[code] }

因此,根据教程,相应的 Python 包装器(可能)应该是这样的:

complextype = '??????'

_integr = ctypes.CDLL('libintegrand.so')
_integr.integrand.argtypes = (complextype, ctypes.c_double, ctypes.c_double)

def integrand(theta1, r, z):
    global _integr
    result = _integr.integrand(complextype(theta1), ctypes.c_double(r), ctypes.c_double(z))
    return float(result)

但是这个类型应该是什么?我应该怎么做?

如果函数也有一个复杂的参数使它变得更加复杂,请忽略复杂的参数。

天真地,也许把它分成两个参数,Re(z), Im(z) 如果那不是一个选项,也许将参数传递给 python 函数 complex().

这些都是天真的解决方案;也许它们不起作用,但如果您没有考虑过它并且缺乏更好的响应,可能值得尝试。

祝你好运!

创建一个小的 C 包装函数:

void integrand_wrapper(float *re, float *im, double r, double z)
{
    float _Complex  result;
    float _Complex  theta = (*re) + I*(*im);
    result = integrand(theta, r, z);
    (*re) = creal(result);
    (*im) = cimag(result);
}

reim 指针在调用时保存 theta 的实部和虚部,之后保存结果的实部和虚部。

在您的 Python 代码中,使用

调用 integrand_wrapper()
def integrand(theta, r, z):
    global _integr
    theta = complex(theta)
    re = c_float(theta.real)
    im = c_float(theta.imag)
    _integr.integrand_wrapper(byref(re), byref(im), c_double(r), c_double(z))
    return complex(float(re), float(im))

请注意,如果 integrand() 在您无法修改的二进制库中定义,您始终可以创建另一个仅包含 integrand_wrapper 的动态库,动态链接(在 C 中)到原始二进制文件图书馆。

总的来说,我认为增加的开销一点也不重要。这当然值得测试。