将extern "C"放入C ++代码到底能做什么?
例如:
extern "C" {
void foo();
}
#1楼
extern“ C”旨在由C ++编译器识别,并通知编译器所注明的功能已(或将要)以C样式进行编译。 这样,在链接时,它会链接到C中正确版本的函数。
#2楼
它通知C ++编译器在链接时以C样式查找这些函数的名称,因为在链接阶段,用C和C ++编译的函数的名称不同。
#3楼
它以一种可从C调用该函数的方式更改函数的链接。实际上,这意味着函数名称不会被修饰 。
#4楼
extern“ C”使C ++中的函数名称具有'C'链接(编译器不会更改名称),以便客户端C代码可以使用'C'兼容的头文件链接到(即使用)您的函数,该头文件仅包含函数的声明。 函数定义以二进制格式(由C ++编译器编译)包含,客户端“ C”链接器随后将使用“ C”名称链接至该二进制文件。
由于C ++具有重载的函数名,而C没有重载,因此C ++编译器不能仅使用函数名作为要链接的唯一ID,因此它通过添加有关自变量的信息来破坏名称。 AC编译器不需要处理名称,因为您不能在C中重载函数名称。当您声明函数在C ++中具有外部“ C”链接时,C ++编译器不会将参数/参数类型信息添加到用于连锁。
众所周知,您可以显式地为每个单独的声明/定义指定“ C”链接,也可以使用一个块对一系列声明/定义进行分组以具有一定的链接:
extern "C" void foo(int);
extern "C"
{
void g(char);
int i;
}
如果您关心技术方面的问题,它们会在C ++ 03标准的7.5节中列出,此处是一个简短的摘要(着重于外部“ C”):
extern“ C”是一个链接规范
每个编译器都需要提供“ C”链接
链接规范应仅在命名空间范围内发生
所有函数类型,函数名称和变量名称都具有语言链接。 请参阅Richard的注释:只有具有外部链接的函数名称和变量名称才具有语言链接。
即使语言相同,具有不同语言链接的两个函数类型也都是不同类型
链接规格嵌套,内部决定最终的链接
类成员忽略外部“ C”
最多一个具有特定名称的函数可以具有“ C”链接(无论名称空间如何)
extern“ C”强制函数具有外部链接(不能使其静态) 请参见Richard的评论: 'extern“ C”'内部的'static'有效; 如此声明的实体具有内部链接,因此没有语言链接
从C ++到其他语言定义的对象以及从其他语言到C ++定义的对象的链接是实现定义的和语言相关的。 只有两种语言实现的对象布局策略足够相似时,才能实现这种链接
#5楼
在每个C ++程序中,所有非静态函数在二进制文件中均以符号表示。 这些符号是特殊的文本字符串,可唯一标识程序中的功能。
在C语言中,符号名称与函数名称相同。 这是可能的,因为在C中,没有两个非静态函数可以具有相同的名称。
由于C ++允许重载,并且具有C所不允许的许多功能(例如类,成员函数,异常规范),因此无法简单地将函数名用作符号名。 为了解决这个问题,C ++使用了所谓的名称修饰,将函数名称和所有必要的信息(例如参数的数量和大小)转换为一些仅由编译器和链接器处理的怪异字符串。
因此,如果将函数指定为extern C,则编译器不会对其进行名称修饰,并且可以使用其符号名作为函数名称直接对其进行访问。
这在使用dlsym()和dlopen()调用此类函数时非常方便。