我决定将我的一些Python函数移植到C中,主要遵循this simple tutorial。问题是我的C函数返回一个复杂的浮点数,并且在ctypes的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)
但是这种类型应该是什么呢?我该怎么做呢?
如果函数也有一个复杂的参数,这使得它变得更加复杂,请忽略这个复杂的参数。
发布于 2018-07-29 14:32:30
创建一个小的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语言)动态链接到原始二进制库。
总体而言,我认为增加的开销根本不是很重要。这当然是值得测试的。
发布于 2018-07-29 05:15:15
很天真地,可以将它分成两个参数,如果不能这样做,可以将参数传递给Re(z), Im(z)
函数complex()
。
这些都是天真的解决方案;也许它们不起作用,但如果你没有考虑过,在缺乏更好的回应的情况下,可能值得一试。
祝好运!
https://stackoverflow.com/questions/51575212
复制相似问题