将外部“C”放入C++代码中具体做什么?
例如:
extern "C" {
void foo();
}
将外部“C”放入C++代码中具体做什么?
例如:
extern "C" {
void foo();
}
当前回答
它通知C++编译器在链接时以C样式查找这些函数的名称,因为在链接阶段,用C和C++编译的函数的名称不同。
其他回答
在不与其他好答案冲突的情况下,我将添加一点我的示例。
C++编译器的作用是:它在编译过程中破坏了名称,因此我们需要告诉编译器要特别对待C实现。
当我们制作C++类并添加外部“C”时,我们告诉C++编译器我们正在使用C调用约定。
原因(我们从C++调用C实现):要么我们想从C++调用C++函数,要么从C调用C++函数(C++类…等在C中不起作用)。
最近,gcc似乎也支持名称篡改。即使在外部“c”中,如果使用类或重载,它也会自动损坏。
#include <stdio.h>
extern "C"{
struct myint{
int i;
};
struct myint2
{
int a;
myint2(int a): a(a) {};
operator myint() const {return myint{a};}
};
}
void f1(myint i){
printf("%d", i.i);
}
int main(){
myint2 a(1);
f1(a);
}
我甚至使用了许多cpp功能。但代码编译和运行正常。如果你nm,你可以看到main没有损坏,但myint是损坏的。
当混合使用C和C++时(即a.从C++调用C函数;b.从C调用C++函数),C++名称混乱会导致链接问题。从技术上讲,只有当被调用函数已经使用相应的编译器编译成二进制(很可能是*.a库文件)时,才会出现此问题。
因此,我们需要使用外部“C”来禁用C++中的名称篡改。
请参阅下面的链接,该链接是Geeks for Geeks对外部“C”用法的解释。从下面的页面添加重要信息。
考虑函数f()的以下声明
int f (void) { return 1; }
int f (int) { return 0; }
void g (void) { int i = f(), j = f(0); }
C++编译器可能会将上述名称更改为以下名称(来源:Wiki)
int __f_v (void) { return 1; }
int __f_i (int) { return 0; }
void __g_v (void) { int i = __f_v(), j = __f_i(0); }
https://www.geeksforgeeks.org/extern-c-in-c/
我只是想添加一些信息,因为我还没有看到它发布。
您将经常看到C头中的代码,如下所示:
#ifdef __cplusplus
extern "C" {
#endif
// all of your legacy C code here
#ifdef __cplusplus
}
#endif
这实现的是,它允许您在C++代码中使用C头文件,因为宏__cplusplus将被定义。但是您也可以将它与遗留的C代码一起使用,因为宏没有定义,所以它不会看到唯一的C++构造。
虽然,我也见过C++代码,例如:
extern "C" {
#include "legacy_C_header.h"
}
我想这也能完成同样的事情。
不知道哪种方式更好,但我都见过。