什么时候用简单的单词使用extern“C”?

时间:2010-05-09 06:11:06

标签: c++ c extern-c

也许我不理解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库时,是否必须使用它?

7 个答案:

答案 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 ;.

您可能也对Mixing C and C++ from the C++ FAQ Lite感兴趣。

答案 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代码调用。