将外部“C”放入C++代码中具体做什么?

例如:

extern "C" {
   void foo();
}

当前回答

仅仅通过在外部“C”中包装,并不能使任何C标头与C++兼容。当C标头中的标识符与C++关键字冲突时,C++编译器会对此进行投诉。

例如,我看到以下代码在g++中失败:

extern "C" {
struct method {
    int virtual;
};
}

Kinda是有道理的,但在将C代码移植到C++时需要记住。

其他回答

extern“C”使C++中的函数名具有C链接(编译器不会损坏该名称),以便客户端C代码可以使用仅包含函数声明的C兼容头文件链接到(使用)您的函数。函数定义包含在二进制格式(由C++编译器编译)中,然后客户端C链接器将使用C名称链接到该格式。

由于C++有函数名的重载,而C没有,所以C++编译器不能仅将函数名用作链接到的唯一id,因此它通过添加有关参数的信息来破坏名称。C编译器不需要更改名称,因为您不能重载C中的函数名。当您声明函数在C++中具有外部“C”链接时,C++编译器不会将参数/参数类型信息添加到用于链接的名称中。

正如您所知,您可以显式指定每个单独声明/定义的外部“C”链接,或使用块将声明/定义序列分组以具有特定链接:

extern "C" void foo(int);
extern "C"
{
   void g(char);
   int i;
}

如果您关心技术细节,请参见C++03标准第7.5节,这里有一个简短的总结(重点是外部“C”):

外部“C”是链接规范每个编译器都需要提供“C”链接链接规范只能出现在命名空间范围内所有函数类型、函数名和变量名都有语言链接参见Richard的评论:只有具有外部链接的函数名和函数名才有语言链接具有不同语言链接的两种函数类型是不同的类型,即使在其他方面相同连杆规格嵌套,内部规格决定最终连杆类成员忽略外部“C”最多一个具有特定名称的函数可以具有“C”链接(无论名称空间如何)外部“C”强制一个函数具有外部链接(不能使其成为静态的)参见Richard的评论:外部内部的静态“C”是有效的;这样声明的实体具有内部链接,因此没有语言链接从C++到用其他语言定义的对象以及从其他语言到用C++定义的对象的链接是由实现定义的,并且依赖于语言。只有当两种语言实现的对象布局策略足够相似时,才能实现这种链接

在每个C++程序中,所有非静态函数都在二进制文件中表示为符号。这些符号是唯一标识程序中函数的特殊文本字符串。

在C中,符号名与函数名相同。这是可能的,因为在C中没有两个非静态函数可以具有相同的名称。

因为C++允许重载,并且具有许多C不具备的特性——比如类、成员函数、异常规范——所以不可能简单地使用函数名作为符号名。为了解决这个问题,C++使用了所谓的名称篡改,它将函数名和所有必要的信息(如参数的数量和大小)转换为一些只有编译器和链接器才能处理的奇怪字符串。

因此,如果将函数指定为extern C,编译器不会对其执行名称修改,而是可以直接使用其符号名作为函数名进行访问。

这在使用dlsym()和dlopen()调用此类函数时很方便。

extern“C”是一个链接规范,用于调用Cpp源文件中的C函数。我们可以调用C函数、编写变量和包含头。函数在外部实体中声明,并在外部定义。语法为

类型1:

extern "language" function-prototype

类型2:

extern "language"
{
     function-prototype
};

eg:

#include<iostream>
using namespace std;

extern "C"
{
     #include<stdio.h>    // Include C Header
     int n;               // Declare a Variable
     void func(int,int);  // Declare a function (function prototype)
}

int main()
{
    func(int a, int b);   // Calling function . . .
    return 0;
}

// Function definition . . .
void func(int m, int n)
{
    //
    //
}

我只是想添加一些信息,因为我还没有看到它发布。

您将经常看到C头中的代码,如下所示:

#ifdef __cplusplus
extern "C" {
#endif

// all of your legacy C code here

#ifdef __cplusplus
}
#endif

这实现的是,它允许您在C++代码中使用C头文件,因为宏__cplusplus将被定义。但是您也可以将它与遗留的C代码一起使用,因为宏没有定义,所以它不会看到唯一的C++构造。

虽然,我也见过C++代码,例如:

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

我想这也能完成同样的事情。

不知道哪种方式更好,但我都见过。

它以这样一种方式更改函数的链接,即该函数可以从C调用。实际上,这意味着函数名不会被破坏。