我在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",它可以工作。 如何处理?
答案 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_
符号。