2011-11-03 114 views
5

我知道如何使用extern "C"但是您必须使用它的条件是什么?何时使用extern“C”?

extern "C"告诉C++编译器不执行任何名称重整上 大括号内的代码。这使您可以在C++中从 调用C函数。

例如:

#include <string.h> 

int main() 
{ 
    char s[] = "Hello"; 
    char d[6]; 

    strcpy_s(d, s); 
} 

虽然这种编译VC++的罚款。但有时这写成:

extern "C" { 
#include <string.h> 
} 

我没有看到这一点。你能举一个真实的例子,extern "C"是必要的吗?

+7

而是黑客''避免名字改编的,使用''标题。 –

+0

@AlexandreC:使用''标题绝对不是一个好主意。 ''头部*不*保证将标识符放置在全局名称空间中,从而在代码移动到其他编译器时破坏依赖于全局名称空间标识符的代码。另外,''头可能并且实际上会将标识符放置在全局名称空间中,因此理论上也会破坏依赖于无污染全局名称空间的代码。 “理论上”虽然过于模糊,至少有一个白痴做到了。所以,不要使用它们。 –

+0

@ AlfP.Steinbach:如果您编写C++,请使用''。如果你编写C,使用''和**用C编译器**编译你的代码。混合语言不是一个好主意。 –

回答

4

当您从库中导出函数时,会出现一个非常常见的用途extern "C"。如果您不禁用C++名称修改,则可以使库的客户非常难以命名您的函数。同样的,当你走向另一个方向时,当你导入一个已经用C链接导出的函数时。

6

您可以使用extern "C"来防止头文件中的名称变形,以及您的C++对象文件用于库或已经编译时没有变形的对象。

例如,假设您有一个widget库,该库使用C编译器进行编译,以使其发布的接口不受损坏。

如果在代码中包含头文件,它会假定的名称是,并且这些损坏的版本是您要链接器查找的内容。

但是,由于您会要求类似[email protected]_float_charptrwidget图书馆将只发布function,您将遇到问题。

但是,如果包括它:

extern "C" { 
    #include "widget.h" 
} 

你的编译器会知道它应尽量选用function,非错位版本。

这就是为什么,在对C东西头文件意指包括用C _or C++程序,你会看到的东西,如:

#ifdef __cplusplus 
    extern "C" { 
#endif 

// Everything here works for both C and C++ compilers. 

#ifdef __cplusplus 
    } 
#endif 

如果您使用的是C编译器,包括这一点,#ifdef线将导致extern "C"东西消失。对于C++编译器(其中__cplusplus已定义),所有内容都将不受损坏。

+0

为什么还有第二个'#ifdef __cplusplus'? – user103214

+0

@ user974191:用于右大括号,否则大括号将不平衡。 – paxdiablo

1

当您用C写的库链接时,告知编译器不要装饰名称,以便链接器可以找到函数。在C++函数名称等中有链接器的信息,例如参数名称中包含的参数类型和大小。

1

如果您正在生成一个二进制库A,该二进制库A公开了您想要从二进制B调用的函数。

想象一下A是A.dll而B是B.exe,并且您在Windows系统上。

C++没有描述B的知道如何调用A的二进制布局。通常,这个问题通过使用相同的编译器生成A和B来解决。如果您想要更通用的解决方案,请使用extern关键字。这以C方式公开该功能。 C确实描述了一种二进制格式,以便来自不同编译器的不同二进制文件可以相互交谈。

参见: http://en.wikipedia.org/wiki/Application_binary_interface http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

1

如果,你的C++代码中,你#include一个外部库(在C语言编写的)头,如果功能有没有宣布extern "C"他们不会工作(你在链接时会得到未定义的参考)。

但这些天来,人们编码C库,并提供头文件你会知道,而且经常把extern "C"在他们的头文件(与#ifdef __cplusplus适当保护)

也许有更好的方式来了解是使用(假设你有一个Linux系统)nm实用程序来显示库或可执行文件中使用的(unmangled)名称。

3

下面是一个具体的事例破解的例子,需要修复extern "C"

module.h

int f(int arg); 

module.c

int f(int arg) { 
    return arg + 1; 
} 

main.cpp

#include "module.h" 

int main() { 
    f(42); 
} 

因为我混合使用C和C++,所以它不会链接(两个目标文件,只有一个会知道其C++错位名称下的f)。

也许是为了解决这个问题最彻底的方法是通过使头文件与C和C++兼容:

module.h

#ifdef __cplusplus 
    extern "C" { 
#endif 

int f(int arg); 

#ifdef __cplusplus 
    } 
#endif 
+0

+1这解释了我在找什么。 – user103214