何时使用外部"C"?

When to use extern "C"?

本文关键字:外部 何时使      更新时间:2023-10-16

我知道如何使用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"的真实例子吗?

您使用extern "C"来防止头文件和c++对象文件中的名称混淆对于已经编译过的库或对象

例如,假设你有一个widget库,它是用C编译器编译的,所以它发布的接口是无篡改的。

如果您将头文件原样包含到您的代码中,它将假定名称是混乱的,并且这些混乱的版本是您将告诉链接器查找的。

然而,由于您将要求function@intarray_float_charptr之类的东西,而widget库将只发布function,因此您将遇到问题。

但是,如果你用:

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

你的编译器将知道它应该尝试使用function,未修改的版本。

这就是为什么,在C或c++程序中包含的C内容的头文件中,您会看到这样的内容:

#ifdef __cplusplus
    extern "C" {
#endif
// Everything here works for both C and C++ compilers.
#ifdef __cplusplus
    }
#endif

如果你使用C编译器来包含这个,#ifdef行会导致extern "C"的东西消失。对于c++编译器(其中定义了__cplusplus),所有内容都是非mangmanged的。

当您从库导出函数时,extern "C"的一个非常常见的用途。如果你不禁用c++的名称混淆,那么你的库的客户端很难命名你的函数。同样地,在另一个方向上,当您导入使用C链接导出的函数时。

这是一个具体的例子,事情打破了,需要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++,这不会链接(在两个目标文件中,只有一个会知道f在其c++名称下)。

也许解决这个问题最干净的方法是使头文件同时兼容C和c++:

module.h :

#ifdef __cplusplus
  extern "C" {
#endif
int f(int arg);
#ifdef __cplusplus
  }
#endif

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

如果你正在生成一个二进制库a,它公开了一个你想从二进制b中调用的函数

假设A是A.dll, B是B.exe,你在Windows系统上。

c++没有描述二进制布局,使得B知道如何调用a。通常这个问题可以通过使用相同的编译器来生成a和B来解决。如果你想要一个更通用的解决方案,你可以使用extern关键字。这将以C的方式公开函数。C确实描述了一种二进制格式,这样来自不同编译器的不同二进制文件就可以相互通信。

看:http://en.wikipedia.org/wiki/Application_binary_interfacehttp://en.wikipedia.org/wiki/Name_mangling Name_mangling_in_C.2B.2B

如果,在你的c++代码中,你#include一个外部库的头(用C编码),如果函数中没有声明extern "C",它们就不能工作(你会在链接时得到未定义的引用)。

但是现在,编写C库并为您提供头文件的人往往知道这一点,并且经常将extern "C"放在他们的头文件中(适当地使用#ifdef __cplusplus保护)

也许更好的理解方法是使用(假设您有Linux系统)nm实用程序来显示库或可执行文件中使用的(未修改的)名称。