代码之家  ›  专栏  ›  技术社区  ›  Adam Holmberg

将头部中的“外部”C声明为C++共享库的效果是什么?

  •  6
  • Adam Holmberg  · 技术社区  · 14 年前

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

    我有一个用C++编译器编译的“.SO”共享库。头部有一个“typedef stuct”和许多函数声明。如果头包含外部“c”声明…

    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
      // typedef struct ...;
      // function decls
    
    #ifdef __cplusplus
    }
    #endif
    

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

    在这种情况下,有没有理由要有外部“C”声明?

    5 回复  |  直到 14 年前
        1
  •  12
  •   Stephen    14 年前

    这一点很重要,这样编译器就不会将mangle命名为mangle。C++使用名称修改来区分函数与操作符重载。

    运行“/Ur/bin /nm”,以二进制来查看C++对函数名的作用: _ zst8_破坏9_u gnu_cxx17_u normal_u iteratoripist6矢量是ieeeevt_s7_said0_e

    外部“c”防止这个名字被弄坏。

    IIRC,这使得程序可以在运行时动态链接符号。“插件”类型的架构很常见。

        2
  •  4
  •   Dror Helper    14 年前

    编译C++时,方法名称会改变(Mangle)-并且不能从另一个使用C的DLL/EXE调用该方法。

    为了保留类和方法名,您需要将它们编译为“c”,而不需要名称损坏。

    库仍然是一个C++库,但是它将一些声明(在Extn中的一个)“块”暴露为C方法。

        3
  •  3
  •   msw    14 年前

    这个 #ifdef 看守的 extern 声明是告诉C链接器这些符号有C(未组合)符号表条目。这个 大花 确保C编译器编译的代码单元(文件)没有任何影响。

        4
  •  0
  •   R Samuel Klatchko    14 年前

    不利于使用 extern "C" 对于C++ API来说,它防止了函数重载:

    extern "C"
    {
        // ILLEGAL - C linkage does not support function overloading
        void foo(int x);
        void foo(const char *str);
    }
    
        5
  •  0
  •   quamrana    14 年前

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

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

    对于静态链接或与共享库的链接都不应该有任何影响。