通过ctypes将Python与Fortran模块连接起来

时间:2017-03-29 02:06:02

标签: python fortran ctypes

我在Fortran中有这个模块:

  MODULE utils
  IMPLICIT NONE
  PUBLIC
  INTEGER :: num_atom ! number of atoms in one configuration
    CONTAINS
      SUBROUTINE readin
      IMPLICIT NONE
      INTEGER :: iargc, ndim, i

     END SUBROUTINE readin

     SUBROUTINE convert
     IMPLICIT NONE
     REAL :: x,y,z
     END SUBROUTINE convert

我通过以下方式编译:

gfortran -shared -fPIC -cpp -O2 thiscode.f90 -o somelib.so

所以,在尝试调用函数时,#read;"来自以下python代码:

import os
_path = os.path.dirname(os.path.realpath(__file__)) + "/" + "somelib.so"

from ctypes import cdll, byref, c_int, c_double, c_char
lib_polint = cdll.LoadLibrary(_path)

def A():
    a = lib_polint.readin_

A()

我无法将函数的名称识别为" somelib.so"并出现以下错误:

"未定义的符号:readin _"。

如果我删除模块并只保留子程序" readin",它可以工作。 如何处理?

2 个答案:

答案 0 :(得分:0)

转储共享库中的符号

$ nm -D somelib.so
0000000000201020 B __bss_start
                 w __cxa_finalize
0000000000201020 D _edata
0000000000201028 B _end
00000000000006f4 T _fini
                 w __gmon_start__
00000000000005a0 T _init
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
00000000000006e0 T __utils_MOD_convert
0000000000201024 B __utils_MOD_num_at
00000000000006f0 T __utils_MOD_readin

看起来模块中的子例程会影响符号名称。而不是readin_你有__utils_MOD_readin。如果删除周围的模块并将子程序保留在顶层,那么您将获得预期的符号名称。

为了记录,我只是报告我在系统上看到的内容。我对fortran不熟悉,也不知道你是否可以依赖编译器的命名。

答案 1 :(得分:0)

使用Fortran与C的互操作性将链接器符号设置为您想要的任何内容

 SUBROUTINE readin bind(C, name="readin")
  INTEGER :: iargc, ndim, i

 END SUBROUTINE readin

现在,作为外部可见C函数的子程序的名称将只是readin,您不必担心名称错误。

如果没有模块,您可以打赌名称为_readin,但它也可以是readin__readin_,但不是经常。

对于模块而言,这是一个乐透,编译器之间的名称错误确实不同。没有必要使用_MOD_符号。