从python中的共享fortran库调用函数

时间:2011-04-27 23:35:48

标签: python fortran fortran-iso-c-binding

我想从Python中的Fortran共享库中调用一些函数。我在网上找到了一些链接并阅读它们,根据我的发现,我应该做

libadd = cdll.LoadLibrary('./libbin.so') 

加载共享对象。但是,此共享对象包含来自另一个共享库的一些符号。我阅读了cdll的帮助,但似乎无法同时加载多个共享对象文件。我怎样才能从这个Fortran库中调用函数,这很可能是由英特尔Fortran编译器编译的?

3 个答案:

答案 0 :(得分:17)

您需要知道共享对象中函数的签名。您是否有源代码或一些解释函数名称和参数类型的参考?

例如,我有这个源代码( mult.f90 ):

integer function multiply(a, b)
    integer, intent(in) :: a, b
    multiply = a * b
end function multiply

..为了演示如何一次加载和使用多个共享对象,我也有( add.f90 ):

integer function addtwo(a, b)
    integer, intent(in) :: a, b
    addtwo = a + b
end function addtwo

编译,检查符号:

% gfortran-4.4 -shared -fPIC -g -o mult.so mult.f90
% gfortran-4.4 -shared -fPIC -g -o add.so add.f90
% nm -ao mult.so | grep multiply
mult.so:00000000000005cc T multiply_

请注意,共享对象中的符号名称附加了下划线。由于我有源代码,因此我知道签名为multiply_(int *a, int *b),因此很容易从ctypes调用该函数:

from ctypes import byref, cdll, c_int

mult = cdll.LoadLibrary('./mult.so')
add = cdll.LoadLibrary('./add.so')
a = c_int(2)
b = c_int(4)
print mult.multiply_(byref(a), byref(b))
print add.addtwo_(byref(a), byref(b))

输出:

8
6

答案 1 :(得分:5)

我会添加@sameplebias答案,可以使用iso_c_binding模块强制(任何)fortran编译器生成正确的C签名。用法示例:

module fmesh_wrapper

use iso_c_binding, only: c_double, c_int
use fmesh, only: mesh_exp

implicit none

contains

subroutine c_mesh_exp(r_min, r_max, a, N, mesh) bind(c)
real(c_double), intent(in) :: r_min
real(c_double), intent(in) :: r_max
real(c_double), intent(in) :: a
integer(c_int), intent(in) :: N
real(c_double), intent(out) :: mesh(N)
call mesh_exp(r_min, r_max, a, N, mesh)
end subroutine

! wrap more functions here
! ...

end module

这将具有以下C签名:

void c_mesh_exp(double *r_min, double *r_max, double *a, int *N,
        double *mesh);

然后你可以照常从Python调用它。这种方法的优点是它适用于所有平台(不使用任何特殊的编译器选项)。

答案 2 :(得分:1)

要使f2py(来自NumPy)工作,请从@samplebias借用mult.f90add.f90示例。在shell中,编译Python可导入的共享库:

f2py -c -m mult mult.f90
f2py -c -m add add.f90

现在在Python中使用它们:

>>> import add
>>> import mult
>>> add.addtwo(4, 5)
9
>>> mult.multiply(4, 5)
20