尝试使用 C++ 代码调用 fortran 子例程时出现链接错误

Link error when trying to call a fortran subroutine using C++ code

提问人:Christ Liu 提问时间:4/20/2023 最后编辑:Vladimir F Героям славаChrist Liu 更新时间:4/20/2023 访问量:170

问:

我目前正在尝试在我的 C++ 程序中使用一些 fortran 子例程。但是,我以前从未尝试过,所以我写了一个简单的代码示例来尝试混合编程。

我有“gcc 版本 12.1.0 (GCC)”和“Apple clang 版本 14.0.0 (clang-1400.0.29.202)”。我的操作系统是macOS Monterey 12.6。

Fortran 代码(test_f.f90)如下:

subroutine PRINT_NUMBER()
    use iso_c_binding 
    implicit none

    write(*,*) "This is fortran answering!"
    
end subroutine PRINT_NUMBER

它只是做一个简单的打印过程。

C++代码(test_c.cpp)如下:

#include <iostream>

extern "C"
{
    void print_number_();
}

int main()
{
    std::cout << "This is C++ answering!" << std::endl;
    print_number_();

    return 0;
}

它调用 fortran 代码文件中的子例程来打印“这是 fortran 应答!”并打印“这是 C++ 应答!”本身。

我使用gfortran(gcc版本12.1.0)编译fortran代码,使用g++(Apple clang版本14.0.0)编译C++代码:

gfotran -c test_f.f90
g++ -c test_c.cpp

我得到了两个对象文件test_f.o 和 test_c.o

然后我尝试链接这两个对象文件:

g++ -o a.out test_f.o test_c.o

我收到如下错误消息:

ld: warning: object file (test_f.o) was built for newer macOS version (12.5) than being linked (12.0)
Undefined symbols for architecture x86_64:
  "__gfortran_st_write", referenced from:
      _print_number_ in test_f.o
  "__gfortran_st_write_done", referenced from:
      _print_number_ in test_f.o
  "__gfortran_transfer_character_write", referenced from:
      _print_number_ in test_f.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我注意到 gfortran 库在这里不起作用,所以我使用以下命令找到 gfortran 库:

locate libgfortran

我得到了

/usr/local/Cellar/gcc/10.2.0/lib/gcc/10/libgfortran.5.dylib
/usr/local/Cellar/gcc/10.2.0/lib/gcc/10/libgfortran.a
/usr/local/Cellar/gcc/10.2.0/lib/gcc/10/libgfortran.dylib
/usr/local/Cellar/gcc/10.2.0/lib/gcc/10/libgfortran.spec
/usr/local/gfortran/lib/libgfortran.5.dylib
/usr/local/gfortran/lib/libgfortran.a
/usr/local/gfortran/lib/libgfortran.dylib
/usr/local/gfortran/lib/libgfortran.la
/usr/local/gfortran/lib/libgfortran.spec

我再次尝试使用静态库libgfortran.a来链接对象:

g++ -o a.out /usr/local/gfortran/lib/libgfortran.a test_c.o test_f.o

除了一些“警告:目标文件 (/usr/local/gfortran/lib/libgfortran.a(...))是为比链接 (12.0) 更新的 macOS 版本 (12.3) 构建的“警告我收到:

Undefined symbols for architecture x86_64:
  "___divtf3", referenced from:
      _determine_en_precision in libgfortran.a(write.o)
      _get_float_string in libgfortran.a(write.o)
  "___eqtf2", referenced from:
      _get_float_string in libgfortran.a(write.o)
  "___gttf2", referenced from:
      _determine_en_precision in libgfortran.a(write.o)
      _get_float_string in libgfortran.a(write.o)
  "___letf2", referenced from:
      _get_float_string in libgfortran.a(write.o)
  "___lttf2", referenced from:
      _determine_en_precision in libgfortran.a(write.o)
      _get_float_string in libgfortran.a(write.o)
  "___multf3", referenced from:
      _determine_en_precision in libgfortran.a(write.o)
      _get_float_string in libgfortran.a(write.o)
  "___subtf3", referenced from:
      _determine_en_precision in libgfortran.a(write.o)
      _get_float_string in libgfortran.a(write.o)
  "___unordtf2", referenced from:
      _determine_en_precision in libgfortran.a(write.o)
      _get_float_string in libgfortran.a(write.o)
  "_quadmath_snprintf", referenced from:
      _determine_en_precision in libgfortran.a(write.o)
      _get_float_string in libgfortran.a(write.o)
  "_strtoflt128", referenced from:
      __gfortrani_convert_real in libgfortran.a(read.o)
      __gfortrani_convert_infnan in libgfortran.a(read.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

它仍然没有用。看来我在这里需要更多的库。我很困惑。

C++ macOS Fortran Clang Linker-错误

评论

0赞 Vladimir F Героям слава 4/20/2023
欢迎,我建议参观。请注意,在您的情况下,这不会有任何作用。您可能希望使用和删除 C 符号名称中的下划线。use iso_c_bindingbind(C)
0赞 Vladimir F Героям слава 4/20/2023
首先,尝试使用 而不是 .然后在使用 时尝试在 link 命令中使用。我强烈建议不要手动引用库。尝试同时链接 libquadmath () 库。gfortrang++-lgfortrang++.a-lquadmath
0赞 Vladimir F Героям слава 4/20/2023
请注意,我们之前有许多关于此的任务,并且有可用的副本,并且您的 questiin 可能会作为副本关闭。
0赞 Vladimir F Героям слава 4/20/2023
好的,谷歌搜索显示这些符号来自 libgcc,所以尝试也添加 .请记住,顺序确实很重要。至少在使用静态库时是这样。我仍然认为主要问题是手动链接库。-lgcc.a
1赞 lastchance 4/20/2023
@Christ Liu,我的建议的意图是,你没有在里面放一个单独的库路径,而只是让特定版本的gcc使用IT期望找到的库。我怀疑问题的主要部分是你有两个不同的编译器(或不同版本的编译器)相互混淆。

答: 暂无答案