使用Cython包装f2py编译的Fortran .so(不通过python)

时间:2014-03-03 09:00:56

标签: python cython f2py

看一些其他类似的问题(Cython and fortran - how to compile together without f2py),我可能会以错误的方式解决这个问题,但是我想要实施的工作流程似乎是cythonic / pythonic,如果以下是不可能的:

1)使用fortran_func.f源文件中的f2py编译fortran_func.so,该文件包含我需要的foo子例程。看到我有.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 个答案:

答案 0 :(得分: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