Fortran语言的Pb<-&燃气轮机;C++;如果我使用-finit local zero选项编译fortran,则具有互操作性 我在用C++和FORTRAN连接程序时发现了一个奇怪的结果。 测试(见后)非常简单:在FORTRAN模块中定义变量并在C++程序中访问它。 如果我使用“-finit local zero”选项编译fortran(GCC 7.4.0中的gfortran),则链接会失败,并抱怨变量的多重定义。当然,如果我抑制这个选项,它工作得很好,但它对我来说是一个pb,因为我需要将我的未初始化数据设置为“0” 我在FORTRAN代码之后,C++代码和EXE.

Fortran语言的Pb<-&燃气轮机;C++;如果我使用-finit local zero选项编译fortran,则具有互操作性 我在用C++和FORTRAN连接程序时发现了一个奇怪的结果。 测试(见后)非常简单:在FORTRAN模块中定义变量并在C++程序中访问它。 如果我使用“-finit local zero”选项编译fortran(GCC 7.4.0中的gfortran),则链接会失败,并抱怨变量的多重定义。当然,如果我抑制这个选项,它工作得很好,但它对我来说是一个pb,因为我需要将我的未初始化数据设置为“0” 我在FORTRAN代码之后,C++代码和EXE.,c++,c++11,gcc,linker,fortran,C++,C++11,Gcc,Linker,Fortran,module A_module USE ISO_C_BINDING implicit none real(C_FLOAT) , bind(C) :: isareal integer(C_INT), bind(C, NAME="MMS") :: MMS CONTAINS subroutine CHANGE() bind(c) use iso_c_binding i

        module A_module

        USE ISO_C_BINDING
        implicit none
        real(C_FLOAT) , bind(C) :: isareal
        integer(C_INT), bind(C, NAME="MMS") :: MMS 

        CONTAINS

        subroutine CHANGE() bind(c)
        use iso_c_binding
        implicit none
        isareal = 5.0 
        MMS=40
        write(*,*) 'fortran changes isareal =>',isareal
        write(*,*) 'fortran changes MMS =>',MMS
        end subroutine CHANGE
        end module
以下是错误(使用-finit local zero时)

谢谢你的帮助……/P> < P>这个问题实际上是(至少部分地)在C++代码中。您没有告诉我,

isaral
MMS
是外部的,因此编译器将为它们生成一个“实例化”符号(引号,因为我不记得正确的术语)。您可以通过例如“readelf-s main.o”看到这一点

这里需要注意的关键点是,
Ndx
列(最后一列的下一列,符号名称旁边)表示
MMS
在第4节中

如果将C++代码添加到<代码> iSARALL 和 MMS声明,您将看到,该节号更改为<代码> UND>代码>,这意味着它是对其他对象文件中的符号的引用,由链接器解决。 难题的第二部分是,如果您使用
-finit local zero
编译Fortran代码,Fortran编译器还将生成“实例化”符号。然后,当你试图将它们链接在一起时,你会得到“多重定义”错误。现在,如果省略
-finit local zero
选项,GFortran将把这两个符号放在
COM
部分(缩写为
COMDAT
),这是一种特殊的部分,允许多个定义。我不知道为什么会这样做,尽管我猜
COMDAT
不允许将符号初始化为某个值

如果你搜索GCC bugzilla,你会发现一堆与多定义问题相关的Fortran问题,所有这些问题在错综复杂的小段落中相互关联。

问题在于

extern "C" {
  void change();
  float isareal;
  int MMS; // 
}
定义这些变量的存储。它不仅仅是宣布它们。 下面是一个简单的例子:

$ cat x.cpp 
extern "C" { int foo; }
$ make x.o
g++    -c -o x.o x.cpp
$ nm x.o
0000000000000000 B foo
extern“C”不使变量为extern;它定义了C约定的链接,即未混合的函数名。由于文件作用域变量名没有损坏(不能重载),因此无需将它们保留在那里:

extern "C" {
  void change();
}
extern float isareal;
extern int MMS;  
我们应该做到这一点


可能是通过使用-finit local zero,您阻止了链接器合并两个完全相同的全局定义

我以为
Pb
lead
的化学名称,但你不是这个意思吧。你所说的
Pb
是什么意思?你的评论说写“彩信”而不是“彩信”很重要。您已经编写了MMS。感谢您的评论:评论“MMS”或“MMS”:它与pb没有直接关系(问题),只是要注意,如果我们没有在fortran中明确地命名绑定(C),name=“MMS”,那么这个变量将变为“MMS”(只是为了不忘记这一点)。“真正的”问题是,我无法使用我在帖子中提到的标志编译fortran代码。在fortran代码中,ATALY写入
MMS=0
是否存在问题(pb)?非常感谢,James,解释很清楚,修改也很好。
0000000000000000     4 OBJECT  GLOBAL DEFAULT    4 MMS
extern "C" {
  void change();
  float isareal;
  int MMS; // 
}
$ cat x.cpp 
extern "C" { int foo; }
$ make x.o
g++    -c -o x.o x.cpp
$ nm x.o
0000000000000000 B foo
extern "C" {
  void change();
}
extern float isareal;
extern int MMS;