如何在 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);
}
re
和 im
指针在调用时保存 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 中)到原始二进制文件图书馆。
总的来说,我认为增加的开销一点也不重要。这当然值得测试。
我决定将我的一些 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);
}
re
和 im
指针在调用时保存 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 中)到原始二进制文件图书馆。
总的来说,我认为增加的开销一点也不重要。这当然值得测试。