When to use extern “C” in simple words?
也许我不理解C和C++之间的区别,但是什么时候以及为什么我们需要使用
1 | extern"C" { |
?显然这是一个"联系公约"。
我简单地读了一下,注意到MSV中包含的所有.h头文件都用它包围了它们的代码。什么类型的代码恰好是"C代码"而不是"C++代码"?我认为C++包含了所有的C代码?
我猜这不是事实,C++是不同的,标准特征/函数存在于一个或另一个,但不是两者(即:Prttf是C和cOutt是C++),但是C++是向后兼容的,但是外部的"C"声明。这是正确的吗?
我的下一个问题取决于第一个问题的答案,但我还是会在这里问:因为用C编写的MSV头文件被外部"C"包围…},您何时需要自己在自己的代码中使用它?如果你的代码是C代码,而你试图在C++编译器中编译它,那么它应该不会有问题,因为你所包括的所有标准的H文件都已经有了C++的编译器中的"外部""C"的东西了吗?
在编译C++时必须使用它,但链接到已经构建的C库还是什么?
在声明在C.中实现/编译的函数时,您需要在C++中使用EDCOX1(0),使用EDCOX1(0)来告诉编译器/链接器使用C命名和调用约定,而不是使用C++名称处理和C++调用约定。对于其他库提供的函数,您几乎不需要使用EDCOX1(0)},而且写的库将已经存在于它向C和C++输出的公共API中。但是,如果您编写一个库,您希望在C和C++中都可用,那么您必须有条件地将其放入头文件中。
至于所有C代码是否是C++代码…不,那不正确。C++是"C的超集",这是一个流行的神话。虽然C++确实力求尽可能与C兼容,但也存在一些不兼容之处。例如,BoOL是有效的C++,但不是有效的C,而BuOL存在于C99中,但在C++中是不可用的。
至于是否需要在系统的.h文件中使用extern"c"…任何设计良好的实现都将在其中为您提供这些功能,这样您就不需要使用它们。但是,为了确保提供了它们,您应该包含以"c"开头并省略".h"的等效头文件。例如,如果包含< cType .h >,几乎任何合理的系统都会添加外部的"C";但是,要保证C++兼容的头,您应该包括头< ccType >。
您可能还感兴趣的是从C++ FAQ Lite中混合C和C++。
其他答案是正确的,但是一个完整的"样板"示例可能会有所帮助。C和/或C++项目中包含C代码的规范方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | // // C_library.h // #ifdef __cplusplus extern"C" { #endif // // ... prototypes for C_library go here ... // #ifdef __cplusplus } #endif |
-
1 2 3 4 5 6 7 8 9 | // // C_library.c // #include"C_library.h" // // ... implementations for C_library go here ... // |
-
1 2 3 4 5 6 7 8 9 10 | // // 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代码。
C++编译器将它们的符号表中的名称与C编译器不同。您需要使用EDCOX1×0声明来告诉C++编译器在创建符号表时使用C约束规则来代替。
当你想在C++编译器编译的代码中使用C调用约定时,你需要使用EDCOX1 0。原因有两个:
您在C中实现了一个函数,并希望从C++调用它。
你有一个函数在C++中实现,并想从C调用它。注意,在这种情况下,你只能在函数接口中使用C++的C部分(没有类,…)。
除了C之外,这也适用于当您想在C++和其他语言之间进行互操作时,它们使用与C相同的调用和命名约定。
通常,C头文件中的声明被
1 2 3 4 5 6 7 8 9 | #ifdef __cplusplus extern"C" { #endif [... C declarations ...] #ifdef __cplusplus } #endif |
使它可以从C++中使用。
EDCOX1的5个块告诉C++编译器使用C命名和调用约定。如果你不使用这个,你会得到链接错误,如果试图包含C库与你的C++项目,因为C++会损坏名称。我倾向于在所有的C标题上使用它,以防万一在C++项目中使用。
1 2 3 4 5 6 7 8 9 | #ifdef __cplusplus extern"C" { #endif /* My library header */ #ifdef __cplusplus } // extern #endif |
我使用"ExtEngC:C"来读取C++代码,而不必导出导出C++ DLL函数时所做的额外名称。否则,有额外的荒谬(或真正的,非英语)字符,我必须添加在C输入端的函数入口点的末尾,以便在DLL中正确访问C++函数。
C++函数是以名字命名的。这使得它们无法直接从C代码调用,除非使用