2010-04-06 83 views
6

根据this question我理解了将C库与C++代码链接起来的目的。现在假设如下:在头文件中声明'extern“C”'到C++共享库的效果是什么?

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

#ifdef __cplusplus 
extern "C" 
{ 
#endif 

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

#ifdef __cplusplus 
} 
#endif 

...有什么影响?具体来说,我想知道是否有任何有害的副作用,因为共享库被编译为C++,而不是C.

是否有任何理由在这种情况下有外部“C”声明?

+0

你的库只能从C++调用,还是你需要从C调用库吗? – 2010-04-06 21:06:20

回答

11

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

运行 “的/ usr/bin中/ nm” 是针对二进制,看看C++做你的函数名: _ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E

的extern “C” 防止名字改编。

IIRC,它使程序可以在运行时动态链接符号。这是“插件”类型体系结构的常见现象。

+0

感谢您的信息。我从包括头文件在内的客户角度思考,而不是导出名称的库。 – 2010-04-06 20:09:35

4

编译C++的方法名称的变化(压延) - 你将无法调用该方法从另一个DLL/EXE使用C.

为了保持你所需要的类和方法名将它们编译为“C”而没有名称混乱。

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

3

#ifdef看守extern声明是告诉C链接器该符号具有C(unmangled)符号表条目。 #ifdef确保在由C编译器编译的代码单元(文件)中没有影响。

0

一个损害使用extern "C"用于C++ API是,它可以避免拥有功能重载:

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

使用'extern“C”'的意义在于C和C++代码共享一个API,而C是最低公分母,因此您必须遵守C编译器强制执行的规则。如果它*是一个C++ API,那么你不会使用'extern“C”'并且只用C++编译器进行编译,一切都会好起来的。 – quamrana 2010-04-06 20:46:06

+1

@quamrana - 他的问题是“对C++共享库有什么影响”。目前还不清楚他是否需要从C代码中调用他的库。 – 2010-04-06 20:52:38

0

#ifdef在示例意味着只有一个C++编译器将看到extern缠绕头文件,其将意味着它会产生没有损坏的名称。 C编译器没有看到extern(它不会理解),但总是会生成非重名的名称。

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

静态链接或与共享库链接应该没有影响。