使用SWIG从Fortran源代码创建Python模块

时间:2016-01-02 16:24:00

标签: python c++ numpy fortran swig

我正在一个涉及为Fortran编写的程序创建Python接口的项目中工作。我做了一些研究并决定使用SWIG,首先将Fortran例程暴露给C ++然后用SWIG包装它们。但是,我在使用Python模块时遇到了麻烦。

举个例子,我有这个Fortran函数:

function sum_array(input_array, length) result(sum)

implicit none

integer, value, intent(in) :: length
real(kind=8), intent(in), dimension(length) :: input_array

real(kind=8) :: sum
integer :: i

sum = 0.0

do i=1, length
   sum = sum + input_array(i)
end do

end function sum_array

使用C声明:

double sum_array(double* input_array, int length);

我使用的SWIG界面文件是:

%module sum_array

%{
   #define SWIG_FILE_WITH_INIT
   #include "sum_array.h"
%}

%include "numpy.i"

%init %{
   import_array();
%}

%apply (double* IN_ARRAY1, int DIM1) {(double* input_array, int length)};

%include "sum_array.h"

此接口文件使用numpy.i接口。

我将此代码(使用make)编译为共享对象,如下所示:

$ swig -python -c++ -o sum_array_wrap.cpp sum_array.i
$ gfortran -c sum_array.f90 -o sum_array.o -fpic -fno-underscoring 
$ gcc -I/usr/include/python2.7 -c sum_array_wrap.cpp -o sum_array_wrap.o -fpic -std=c++0x
$ gfortran sum_array_wrap.o sum_array.o -o _sum_array.so -shared -Wl,-soname,_sum_array.so -lstdc++

当我尝试用Python导入模块时,我得到了" NameError:name' sum_array'未定义",来自:

from numpy.random import rand
from _sum_array import *

input_array = rand(5)
sum = sum_array(input_array)

根据我从解释器中的help()获得的信息,我相信链接器不包括库中的sum_array函数,我认为这是问题所在。

有关如何使其发挥作用的任何想法?

顺便说一句,关于其他工具而不是SWIG的建议非常受欢迎,因为它是我第一次这样做,而我尝试这样做的唯一方法就是这个。

1 个答案:

答案 0 :(得分:0)

这次问题发生在 name mangling 。 fortran sompiler不使用它,因此导出符号名称为sym_array,但稍后您使用C ++编译接口,因此链接器期望看到类似_Z9sum_arrayPdi的内容。解决方案是将标题内容包装到

#ifdef __cplusplus
extern "C" {
#endif

double sum_array(double* input_array, int length);

#ifdef __cplusplus
}
#endif