gcc编译的C程序链接gfortran库遇符号问题,如何不改代码解决?
问题:C调用Fortran库符号不匹配,无需修改代码的解决方法
我在Oracle Linux(红帽衍生版)环境下,用gcc 8.5.0编译的C程序,需要链接同版本gcc编译的C库和未知版本gfortran编译的Fortran库。C库链接正常,但链接Fortran库时出现未定义引用错误——原因是Fortran库导出的符号带有尾下划线。
我的C代码中调用Fortran例程的写法是:
foo_fortran_routine(x, y, z);
如果改成以下写法,链接就不会报错:
foo_fortran_routine_(x, y, z);
这是遗留代码,过去用简单编译选项就能正常运行,我希望不用修改代码就能完成编译链接。用nm命令查看Fortran库的输出如下:
T foo_fortran_routine_
试过gcc和gfortran搭配多种选项链接都无效,只有修改C代码加尾下划线能解决,但这不是理想方案,有没有可行方法?
解决方法
方法1:预编译宏定义自动替换符号
编译C代码时,通过宏定义让预处理器自动将代码中的函数名替换为带下划线的版本:
# 单个函数的情况 gcc -c foo_c_app.c -Dfoo_fortran_routine=foo_fortran_routine_
如果有多个需要替换的函数,可以把所有宏定义写入一个头文件,再通过-include选项引入:
# 先创建宏定义头文件 echo "#define foo_fortran_routine foo_fortran_routine_" > sym_map.h # 编译时引入 gcc -c foo_c_app.c -include sym_map.h
链接阶段正常使用gcc或gfortran完成链接即可。
方法2:链接脚本重定向符号
创建一个链接脚本sym_redirect.lds,内容如下:
SECTIONS { } PROVIDE(foo_fortran_routine = foo_fortran_routine_);
编译链接时指定该脚本,让链接器自动完成符号重定向:
gcc foo_c_app.o -o foo_c_app.exe -L/path/to/fortran/lib -lfortran_lib -T sym_redirect.lds
多个符号需要重定向时,在PROVIDE块中逐个添加即可。
方法3:链接器参数直接定义符号映射
使用gfortran作为链接器时,通过-Wl,--defsym参数直接在链接阶段完成符号重定向:
gfortran foo_c_app.o -o foo_c_app.exe -L/path/to/fortran/lib -lfortran_lib -Wl,--defsym,foo_fortran_routine=foo_fortran_routine_
多个符号的话,重复添加-Wl,--defsym,...参数即可。
内容的提问来源于stack exchange,提问作者Dawn555
相关产品推荐
相关产品推荐

