【问题标题】:Duplicate symbol when linking C++ and Fortran链接 C++ 和 Fortran 时出现重复符号
【发布时间】:2020-03-13 22:06:33
【问题描述】:

链接 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

我有点茫然

【问题讨论】:

    标签: c++ fortran gfortran


    【解决方案1】:

    您的 int __foo_MOD_bar; 定义了一个变量,而不仅仅是声明它(因为 extern "C" 块仅更改链接),并且 Fortran 代码大概也是如此。尝试将显式 extern 说明符添加到变量本身,例如:

    extern int __foo_MOD_bar;
    

    extern "C" int __foo_MOD_bar;extern "C" 块内部或外部的 IIRC 应该也能正常工作)。

    或者,您可以在 Fortran 部分用声明替换变量定义,但我不知道那种语言,所以无法解释。

    【讨论】:

    • 将`extern 添加到extern "C" 中的每个可以解决它。为什么每个变量都需要一个外部变量?
    • extern "C" block 不会将变量定义转换为声明。也就是说,在 Fortran 代码和 C++ 代码中定义了两个具有相同名称的变量。这是不允许的。另一方面,变量本身的extern 说明符使其成为声明,而不是定义。也就是说,一个引用,然后解析为 Fortran 代码中定义的变量(因为它具有相同的名称)。有关更多信息,请参阅en.cppreference.com/w/cpp/language/language_linkage(尤其是注释,有一个类似的示例)。
    【解决方案2】:

    extern "C" 与块一起使用时,块内的变量定义不会得到外部存储类处理。这种行为有一个很好的理由,例如

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-28
      • 1970-01-01
      • 2016-07-21
      • 2021-12-03
      • 1970-01-01
      相关资源
      最近更新 更多