当前位置: 移动技术网 > IT编程>开发语言>C/C++ > extern "C"

extern "C"

2019年07月23日  | 移动技术网IT编程  | 我要评论

91消费宝,herietta,深港图库

我们在使用别人提供的 api 时,经常会看到头文件中有 extern "c" 的字样,有的头文件中写的是

1 #ifdef __cplusplus
2 extern "c" 
3 {
4 #endif
5 ......./*函数声明*/
6 
7 #ifdef __cplusplus
8 }
9 #endif

只有在c++编译中,extern "c" 才会生效。

它的作用是避免 c++ 编译器的 name mangling. 有人说c++编译器在代码后边为我们做了一些意想不到的事,这太可怕了。c++ 大师lippman 调侃说c++编译器具有唯物主义色彩。

那么c++编译器会自动为我们的c++代码做什么事呢?其中比较常见的有自动合成构造函数,析构函数等,还有name mangling。

我们知道c是没有函数重载的,我们不能在c语言中定义多个参数,返回值不同的同名函数,c++是允许的。第一款c++编译器是用c语言实现的(cfront),它将c++代码转换为c语言。那么cfront怎么支持c++的函数重载机制的呢?cfront 对c++函数做了处理,比如以下代码

1 void fun();
2 void fun(char, char);
3 void fun(int);

在经过c++编译器处理后的结果可能是(我会在后续的博文中找到 vc++和g++怎么处理的样例)

1 void fun_v();
2 void fun_c_c(char, char);
3 void fun_i(int);

这样就能够实现同名函数的重载了。

当我们使用

fun('a', 'b');

调用函数的时候,可能转换为

1 fun_c_c('a', 'b');

在第一篇hello world 中,简单说了编译的几个步骤,上边这一步是在compile 的时候做的。(compile 时需要找到这个函数的声明)

最后在link 的阶段,是需要找到该函数的定义的。由于compile 时处理了函数名称,函数定义中的名称也随之更改了。在link的结果中是没有 fun 这个函数的定义的。

如果我们的代码是生产动态链接库(dll 或者 so 文件),那么在 nm 的时候,看到的是处理过的函数名。

回到我们的主题:

extern "c"  c++编译器设置了一个开关,让函数的作者来决定是不是需要做名称处理。如果作者希望c++和c的使用者都可以调用它,一般会加上 extern "c" 的关键字来压制编译器的命名处理。

如果我们拿到一套别人提供的api,这套 api 是c编译器编译的,我们使用c++编译器编译调用api的代码时,经常会出现link时说找不到函数定义。nm 查看动态库的时候发现是有这个函数的,这种情况有两种处理方式:

1. 改用c编译器

2. 在头文件中加上 extern "c" 来抑制c++编译器的命名处理。

如果没有用到c++中的模板,stl,oo等功能,换c语言编译器就行,如果用到了这些,那就将头文件改了吧。

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网