gcc 4.4 与 gcc >4.4 中的默认链接模型

Default linkage model in gcc 4.4 vs. gcc >4.4

我正在尝试使用两个大型、复杂的线性代数库,它们定义了许多相同的函数。我不能重写(在一种情况下是合法的,但在技术上是两种情况)它们中的任何一个。我们称它们为 "special" 和 "normal" 因为我只调用了几个来自 special 的函数。为了始终如一地调用 normal.h 中定义的函数并且仅在某些情况下从 special.h 中定义,我做了这样的事情:

namespace special_space
{
#include "special.h"  // Defines foo()
}

#include "normal.h"   // Defines foo()

int main() {
  foo();                // Calls foo() defined in normal.h
  special_space::foo(); // Calls foo() defined in special.h
}

使用 g++-4.4,这是我开发它时的默认设置,代码可以在没有警告的情况下编译和链接,并且它会按照我的预期和我想要的方式执行。这似乎跨平台、各种 Linux、Unix 和 BSD 环境是一致的。但!如果我用 g++ >4.4 编译,我会收到关于多个 foo() 定义的警告:

In file special.h::line:col: warning: declaration of ‘void special_space::foo()’ with C language linkage [enabled by default]

生成的可执行文件随后在调用 special_space::foo() 时出现段错误。我/认为/在 special.h 中找到的定义中指定 extern "C++" 可能会解决这个问题,但我不允许更改 special.h。所以我该怎么做?更具体地说:

1) 使用g++-4.4安全吗?如果是这样——后续版本发生了什么变化,为什么?

2) 如果指定 C++ 链接模型真的可以解决这个问题,有没有办法告诉 ld 默认使用它?

3) 如果两者都不是——还有其他方法可以从定义同名函数的库中调用函数吗?

因此,正如我在评论中发表的那样,将 headers 包含在

#ifdef __cplusplus
extern "C" {
#endif

#include normal.h

#ifdef __cplusplus
}
#endif

对两个 header 执行此操作。

基本上,由于您从 c++ 链接 c 库,它会进行名称修改(这是允许重载的),您对 c lib 中的符号的调用被链接器修改了。 #ifdef __cplusplus 告诉链接器不要破坏那些特定函数符号的名称。

理想情况下,库的创建者应该将其包含在他们的 header 中,但您提到您无法控制它。我对一些生成的代码有类似的问题。我必须将生成的代码的所有 header 包含在其中,以允许 C++ 调用它。

我不知道,如果没有这个,它是如何工作的。我肯定必须这样做才能回到 gcc < 4.4。