我知道如何使用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"
的真实例子吗?
答案 0 :(得分:7)
使用extern "C"
来防止头文件中的名称损坏以及C ++目标文件,以防止已编译的库或对象没有损坏。
例如,假设您有一个使用C编译器编译的widget
库,以便其发布的接口不受损坏。
如果您将头文件包含在代码中,它将假定名称 被破坏,那些受损版本将是您告诉链接器要查找的内容。
但是,由于您会要求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
),一切都将是非破坏的。
答案 1 :(得分:4)
从库中导出函数时extern "C"
的一个非常常见的用法。如果不禁用C ++名称修改,则可能会使库的客户端很难命名您的函数。同样,当您向另一个方向前进时,当您导入已使用C链接导出的函数时。
答案 2 :(得分:4)
以下是事情中断的具体示例,需要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
答案 3 :(得分:1)
当您使用C extern
编写的库链接时,告诉编译器不要修饰名称,以便链接器可以找到这些函数。在C ++中,函数名称等具有链接器的信息,例如名称中包含的参数类型和大小。
答案 4 :(得分:1)
如果您正在生成一个二进制库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
答案 5 :(得分:1)
如果在C ++代码中,您#include
是外部库的标头(用C编码),如果不的函数声明为extern "C"
,它们将不起作用(你会在链接时得到未定义的引用)。
但是现在,编写C库并为您提供头文件的人倾向于知道这一点,并且经常将extern "C"
放在他们的头文件中(适当地用#ifdef __cplusplus
保护)
或许更好的理解方法是使用(假设您有一个Linux系统)nm
实用程序来向您显示库或可执行文件中使用的(未编码的)名称。