将extern "C"
放入C ++代码到底能作什么? c#
例如: 函数
extern "C" { void foo(); }
extern“ C”旨在由C ++编译器识别,并通知编译器所注明的功能已(或将要)以C样式进行编译。 这样,在连接时,它会连接到C中正确版本的函数。 布局
它通知C ++编译器在连接时以C样式查找这些函数的名称,由于在连接阶段,用C和C ++编译的函数的名称不一样。 spa
它以一种可从C调用该函数的方式更改函数的连接。实际上,这意味着函数名称不会被修饰 。 code
extern“ C”使C ++中的函数名称具备'C'连接(编译器不会更更名称),以便客户端C代码可使用'C'兼容的头文件连接到(即便用)您的函数,该头文件仅包含函数的声明。 函数定义以二进制格式(由C ++编译器编译)包含,客户端“ C”连接器随后将使用“ C”名称连接至该二进制文件。 对象
因为C ++具备重载的函数名,而C没有重载,所以C ++编译器不能仅使用函数名做为要连接的惟一ID,所以它经过添加有关自变量的信息来破坏名称。 AC编译器不须要处理名称,由于您不能在C中重载函数名称。当您声明函数在C ++中具备外部“ C”连接时,C ++编译器不会将参数/参数类型信息添加到用于连锁。 ip
众所周知,您能够显式地为每一个单独的声明/定义指定“ C”连接,也可使用一个块对一系列声明/定义进行分组以具备必定的连接: 字符串
extern "C" void foo(int); extern "C" { void g(char); int i; }
若是您关心技术方面的问题,它们会在C ++ 03标准的7.5节中列出,此处是一个简短的摘要(着重于外部“ C”): get
在每一个C ++程序中,全部非静态函数在二进制文件中均以符号表示。 这些符号是特殊的文本字符串,可惟一标识程序中的功能。 编译器
在C语言中,符号名称与函数名称相同。 这是可能的,由于在C中,没有两个非静态函数能够具备相同的名称。
因为C ++容许重载,而且具备C所不容许的许多功能(例如类,成员函数,异常规范),所以没法简单地将函数名用做符号名。 为了解决这个问题,C ++使用了所谓的名称修饰,将函数名称和全部必要的信息(例如参数的数量和大小)转换为一些仅由编译器和连接器处理的怪异字符串。
所以,若是将函数指定为extern C,则编译器不会对其进行名称修饰,而且可使用其符号名做为函数名称直接对其进行访问。
这在使用dlsym()
和dlopen()
调用此类函数时很是方便。