将标题中的“extern”C“'声明为C ++共享库的影响是什么?

时间:2010-04-06 19:20:42

标签: c++ c linux shared-libraries extern

基于this question我理解了将C库与C ++代码链接起来的构造的目的。现在假设如下:

我有一个用C ++编译器编译的'.so'共享库。标题有一个'typedef stuct'和许多函数声明。如果标题包含extern“C”声明......

#ifdef __cplusplus
extern "C"
{
#endif

  // typedef struct ...;
  // function decls

#ifdef __cplusplus
}
#endif

......效果如何?具体来说,我想知道该声明是否有任何有害的副作用,因为共享库被编译为C ++,而不是C。

在这种情况下,是否有任何理由要使用extern“C”声明?

5 个答案:

答案 0 :(得分:12)

这很重要,因此编译器不会命名mangle。 C ++使用名称修改来区分具有运算符重载的函数。

对二进制文件运行“/ usr / bin / nm”以查看C ++对函数名称的作用: _ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E

extern“C”可以防止名称损坏。

IIRC,使程序可以在运行时动态链接符号。这对于“插件”类型的体系结构来说很常见。

答案 1 :(得分:4)

编译C ++时,方法名称会更改(修改) - 并且您将无法从使用C的其他dll / exe调用该方法。

为了保留类和方法名称,您需要将它们编译为“C”而不会出现名称错误。

该库仍然是一个C ++库,但它将一些声明(extern“c”块中的声明)公开为C方法。

答案 2 :(得分:3)

#ifdef保护extern声明是告诉C链接器符号具有C(未拼写)符号表条目。 #ifdef确保C编译器编译的代码单元(文件)没有任何影响。

答案 3 :(得分:0)

使用extern "C"对C ++ API的一个不利之处在于它会阻止您使用函数重载:

extern "C"
{
    // ILLEGAL - C linkage does not support function overloading
    void foo(int x);
    void foo(const char *str);
}

答案 4 :(得分:0)

示例中的#ifdef表示只有C ++编译器会看到extern包装头文件,这意味着它将生成非损坏的名称。 C编译器没有看到extern(它不会理解),但总是产生非损坏的名称。

这意味着C和C ++编译器将在其目标文件中生成相同的符号,因此无论哪个编译器为声明的函数生成目标代码,所有目标文件都将成功链接,因为符号具有相同的链接和相同的名称。

静态链接或与共享库链接不应有任何影响。