链接C++和Fortran时出现重复符号



我在链接fortran和C++代码时遇到了一个重复的符号错误,我不知道为什么。

我有以下fortran代码,simple.f90:

module foo
use iso_c_binding
integer(kind=c_int) :: bar
end module foo
subroutine print()
use foo
write(*,*) bar
end subroutine print

我有下面的C++驱动程序main.cpp


extern "C"
{
int __foo_MOD_bar;
void print();
}

int main()
{
__foo_MOD_bar = 42;
print();
return 0;
}

我想做的是将模块foo/bar变量分配给一个值,并从Fortran子例程中打印它。

然而,当我编译并链接时

gfortran -std=f2003 -fno-underscoring -c simple.f90
g++ -c main.c
gfortran main.o gfortran.o -o out

我得到一个重复的符号错误

[100%] Linking CXX executable out
duplicate symbol '___foo_MOD_bar' in:
CMakeFiles/out.dir/main.cpp.o
CMakeFiles/out.dir/simple.f90.o
ld: 1 duplicate symbol for architecture x86_64
nm simple.f90.o
00000000000000f8 s EH_frame1
00000000000004cc S ___foo_MOD_bar
U __gfortran_st_write
U __gfortran_st_write_done
U __gfortran_transfer_integer_write
0000000000000000 T _print
0000000000000078 s lC0
nm main.cpp.o
0000000000000388 S ___foo_MOD_bar
0000000000000000 T _main
U _print

我有点不知所措

您的int __foo_MOD_bar;定义了一个变量,而不仅仅是声明它(因为extern "C"块只更改链接(,Fortran代码可能也会这样做。尝试将显式extern说明符添加到变量本身,如:

extern int __foo_MOD_bar;

(extern "C" int __foo_MOD_bar;应该和IIRC一样工作,在extern "C"块内部或外部(。

或者,您可以在Fortran部分中用声明替换变量定义,但我不了解该语言,因此无法解释如何使用。

对块使用extern "C"时,块内的变量定义不会得到外部存储类处理。这种行为有一个很好的理由,即像这样的情况

extern "C" {
#include <some_c_lib.h>
}

以使C头文件在C++中可用。如果extern "C" { ... }将所有变量定义修改为外部声明,那么可能会发生不好的事情。

最新更新