[英]When to use extern “C”?
我知道如何使用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 ++目标文件。
例如,假设您有一个使用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
),一切都将是非破坏的。
从库中导出函数时, 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 ++,因此不会链接(在两个目标文件中,只有一个会在其C ++受损名称下知道f
)。
也许最简单的解决方法是使头文件兼容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_interface http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B
如果在C ++代码中, #include
外部库的头文件(用C编码),如果那里的函数没有声明为extern "C"
那么它们就不会工作(你会在链接时得到未定义的引用)。
但是现在,编写C库并为您提供头文件的人倾向于知道这一点,并且经常将extern "C"
放在他们的头文件中(适当地用#ifdef __cplusplus
保护)
也许更好的理解方法是使用(假设您有一个Linux系统) nm
实用程序来向您显示库或可执行文件中使用的(未编码的)名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.