也许我不理解C和C ++之间的差异,但是我们何时以及为什么需要使用
extern "C" {
?显然它是一个“联系会议”。
我简要地阅读了它,并注意到MSVS附带的所有.h头文件都包含它们的代码。什么类型的代码到底是“C代码”而不是“C ++代码”?我以为C ++包含了所有的C代码?
我猜这不是这种情况,并且C ++是不同的,标准特性/功能存在于一个或另一个中,但不是两个(即:printf是C和cout是C ++),但C ++是倒退的通过extern“C”声明兼容。这是对的吗?
我的下一个问题取决于第一个问题的答案,但无论如何我会在这里问:由于用C语言编写的MSVS头文件被extern“C”{...}包围,你何时需要?在自己的代码中自己使用它?如果您的代码是C代码并且您正在尝试在C ++编译器中编译它,那么它是否应该没有问题,因为您包含的所有标准h文件在C ++编译器中已经有了外部“C”的东西? / p>
在使用C ++进行编译但是链接到已经构建的C库时,是否必须使用它?
答案 0 :(得分:28)
在声明用C语言实现/编译的函数时,需要在C ++中使用extern "C"
。extern "C"
的使用告诉编译器/链接器使用C命名和调用约定,而不是C ++名称修改和C ++调用约定,否则将使用。对于其他库提供的函数,您几乎不需要使用extern "C"
,因为编写良好的库已经将其导入到它导出到C和C ++的公共API中。但是,如果您编写了一个希望在C和C ++中都可用的库,那么您必须有条件地将它放在标题中。
至于所有C代码是否都是C ++代码......不,这是不正确的。 C ++是“C的超集”,这是一个流行的神话。虽然C ++确实尽可能地与C兼容,但有一些incompatibilities。例如, bool 是有效的C ++但不是有效的C,而 _Bool 存在于C99中,但在C ++中不可用。
至于你是否需要在系统的“.h”文件中使用extern“C”....任何精心设计的实现都会为你提供那些,所以你不需要使用它们。但是,为了确保提供它们,您应该包含以“c”开头并省略“.h”的等效头文件。例如,如果包含< ctype.h>,几乎任何合理的系统都会添加extern“C”;但是,要确保与C ++兼容的标头,您应该包含标头< cctype&gt ;.
答案 1 :(得分:17)
其他答案是正确的,但完整的“样板”示例可能会有所帮助。在C和/或C ++项目中包含C代码的规范方法如下:
//
// C_library.h
//
#ifdef __cplusplus
extern "C" {
#endif
//
// ... prototypes for C_library go here ...
//
#ifdef __cplusplus
}
#endif
-
//
// C_library.c
//
#include "C_library.h"
//
// ... implementations for C_library go here ...
//
-
//
// C++_code.cpp
//
#include "C_library.h"
#include "C++_code.h"
//
// ... C++_code implementation here may call C functions in C_library.c ...
//
注意:以上内容也适用于从Objective-C ++调用C代码。
答案 2 :(得分:11)
C ++编译器在符号表中的名称与C编译器不同。在构建符号表时,需要使用extern "C"
声明来告诉C ++编译器使用C mangling约定。
答案 3 :(得分:2)
我使用'extern c'以便C#可以读取我的C ++代码,而无需在导出C ++ dll函数时找出额外的名称。否则,为了正确访问dll中的C ++函数,我必须在C#端的函数入口点的末尾添加额外的无意义(或非真正的非英语)字符。
答案 4 :(得分:2)
extern "C" {}
块告诉C ++编译器使用C命名和调用约定。如果不使用它,如果尝试在C ++项目中包含C库,则会出现链接器错误,因为C ++会破坏名称。我倾向于在我的所有C头文件中使用它,以防万一它们在C ++项目中使用过:
#ifdef __cplusplus
extern "C" {
#endif
/* My library header */
#ifdef __cplusplus
} // extern
#endif
答案 5 :(得分:2)
如果要在C ++编译器编译的代码中使用C调用约定,则需要使用extern "C"
。这有两个原因:
你有一个用C实现的函数,想从C ++中调用它。
你有一个用C ++实现的函数,想要从C调用它。注意,在这种情况下,你只能在函数接口中使用C ++的C部分(没有类,...)。
除了C之外,当您希望在C ++和使用与C相同的调用和命名约定的其他语言之间进行互操作时,这也适用。
通常,C头文件中的声明用
包围#ifdef __cplusplus
extern "C" {
#endif
[... C declarations ...]
#ifdef __cplusplus
}
#endif
使其可以从C ++中使用。
答案 6 :(得分:0)
C ++函数受name mangling的约束。这使得除非使用extern "C"
,否则无法直接从C代码调用。