用Cython封装f2py编译的Fortran .so(不经过Python)
看了一些类似的问题(比如Cython和Fortran - 如何不通过f2py一起编译),我觉得我可能走错了方向,但我想实现的工作流程看起来非常符合Cython/Python的风格,所以我会很惊讶如果下面的事情不可能:
1) 从包含我需要的foo子程序的fortran_func.f源文件中,用f2py编译出fortran_func.so文件。因为我有这个.f源文件,所以我知道正确的函数调用语法。
2) 可能有一个神奇的步骤,涉及到“cdef extern”或者类似的东西。
3) 直接调用这个函数而不需要经过:
import fortran_func
out = fortran_func.foo(x, y)
我的想法是,我在这个函数调用周围有三个for循环,而通过Python导入调用Fortran函数真的很慢。目前我有这个:
import fortran_func
cdef np.ndarray[double, ndim=3] cy_func(double[::1] x,
double[::1] y,
double[::1] z,
int N):
cdef:
int i, j, k
np.ndarray[double, ndim=3] out
out = np.zeros((N, N, N), dtype=np.float64)
for i in range(N): # fast C loops
for j in range(N):
for k in range(N):
# extremely slow python call
out[i,j,k] = fortran_func.foo(x[i], y[j], z[k])
# would prefer a fast, direct function call
# out[i,j,k] = foo(x[i], y[j], z[k])
我非常希望能得到任何帮助,找出这个神奇的步骤应该是什么!
1 个回答
1
你可以用ctypes这个工具直接调用一个共享的Fortran对象,就像调用C语言的函数一样,而不需要把数据转换成Python的类型。你也可以用cython来做到这一点。我在这里写下了相关内容:
http://pythology.blogspot.fr/2014/03/wrapping-fortran-and-python-without-f2py.html
下面是总结:
Fortran文件 add.f95:
subroutine add(a,b,c)
implicit none
integer a,b,c
c = a + b
end
编译命令是:
gfortran -shared -fPIC add.f95 -o add.so
用来调用它的Python代码(注意,'add' 变成了 'add_')是:
#!/usr/bin/env python
from ctypes import c_int, byref, cdll
a = c_int(3)
b = c_int(4)
c = c_int()
addlib = cdll.LoadLibrary('./add.so')
addlib.add_(byref(a),byref(b),byref(c))
print c