我正在尝试将scipy.integrate.nquad
与ctypes
函数一起使用。我完全按照Faster integration using Ctypes上的说明进行操作。
ctypes
集成可以通过几个简单的步骤完成:
- 使用函数签名
醇>double f(int n, double args[n])
在C中编写一个被积函数,其中args
是一个包含函数f
的参数的数组。
//testlib.c double f(int n, double args[n]) { return args[0] - args[1] * args[2]; //corresponds to x0 - x1 * x2 }
- 现在将此文件编译为共享/动态库(快速搜索将有助于此,因为它取决于操作系统)。用户必须链接任何使用的数学库等。在Linux上,这看起来像:
醇>
$ gcc -shared -o testlib.so -fPIC testlib.c
输出库将被称为
testlib.so
,但它可能具有不同的文件扩展名。现在已经创建了一个库,可以使用ctypes
加载到Python中。
- 使用
醇>ctypes
将共享库加载到Python中并设置restypes
和argtypes
- 这允许Scipy解释函数 正确地:
>>> import ctypes >>> from scipy import integrate >>> lib = ctypes.CDLL('/**/testlib.so') # Use absolute path to testlib >>> func = lib.f # Assign specific function to name func (for simplicity) >>> func.restype = ctypes.c_double >>> func.argtypes = (ctypes.c_int, ctypes.c_double)
请注意,无论参数的数量如何,argtypes始终为
(ctypes.c_int, ctypes.c_double)
,并且restype始终为ctypes.c_double
。
- 现在正常使用
集成库函数 醇>nquad
:
>>> integrate.nquad(func, [[0,10],[-10,0],[-1,1]]) (1000.0, 1.1102230246251565e-11)
然而,在最后一步,我没有得到积分的结果,而是出现以下错误:
>>> integrate.nquad(func,[[0,1.0],[-2.0,3.0],[1.0,2.0]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 618, in nquad
return _NQuad(func, ranges, opts).integrate(*args)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 670, in integrate
value, abserr = quad(f, low, high, args=args, **opt)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 254, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 319, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 670, in integrate
value, abserr = quad(f, low, high, args=args, **opt)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 254, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 319, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 670, in integrate
value, abserr = quad(f, low, high, args=args, **opt)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 254, in quad
retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points)
File "/home/bfn097/apps/scipy/0.13.3_mkl-11.1.2_gcc-4.4.7/lib64/python/scipy/integrate/quadpack.py", line 319, in _quad
return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
quadpack.error: quad: first argument is a ctypes function pointer with incorrect signature
我使用的是gcc-4.4.7,python 2.6.6,numpy-1.7.1,scipy-0.13.3
答案 0 :(得分:0)
参数的类型应为:ctypes.POINTER(ctypes.c_double)
但您考虑使用cffi
吗?除了比ctypes
更快之外,你也不必亲自编写参数内容,只需复制C声明并让cffi
解析它们。