1 问题提出
在编程过程中,经常发现如下用法:
#ifndef _FILE_NAME_H_ #define _FILE_NAME_H_ #ifdef __cplusplus extern "C" { #endif ...... #ifdef __cplusplus } #endif
#endif
这样的代码到底是什么意思呢?首先,__cplusplus是cpp中自定义的宏,那么定义了这个宏的话表示这是一段cpp的代码,也就是说,上面的代码的含义是:如果这是一段cpp的代码,那么加入extern "C"{和}处理其中的代码。
要明白为何使用extern "C",还得从cpp中对函数的重载处理开始说起。在c++中,为了支持重载机制,在编译生成的汇编码中,要对函数的名字进行一些处理,加入比如函数的返回类型等等。而在C中,只是简单的函数名字而已,不会加入其他的信息,也就是说:C++和C对产生的函数名字的处理是不一样的,extern "C"的目的就是主要实现C与C++的相互调用问题。
2 c++中调用c函数
使用场景:
1、 由于系统内核一般是使用C语言来编写的,系统内核中用C语言实现了很多库。而上层应用程序有可能是用C++来开发,如果在内核库函数头文件中不用 extern “C”来声明库函数的话,在编写C++应用程序时,包含库头文件,在C++文件链接时就会以C++标准来链接库的函数名,而在库文件实现时是用C来实现的,二者函数名不同,在链接时就会出现找不到函数的现象。
2、在个人开发工程中,个人熟悉使用c++语言,当.cpp文件要调用.c文件中的函数时,需要extern "C"声明.c文件中的函数,在cpp文件中让c++编译器使用c标准链接c文件中函数。
具体实现:
C函数头文件实现:
//c.h #ifndef _c_h_ #define _c_h_ #ifdef __cplusplus extern "C" { #endif void c_fun(); #ifdef __cplusplus } #endif #endif
C函数源文件实现:
#include "c.h" void c_fun() { }
C++调用C函数实现:example.cpp中调用c_func函数,
//example.cpp实现 #include "c.h" int main() { c_fun();
return 0;
}
3 c中调用c++函数
当extern “C”放在函数声明之前,并不会改变函数的编译方式,只是指定编译器按照C的标准链接,而不是按照C++的标准去链接函数。因此,如果c++的库要给c调用,显然,不但要在c++头文件中用该宏和extern "c"括起,在cpp中也要这么做。原因就是让cpp编译器将那些代码,编译成c风格。(在Visual Stduio 2010环境中,在c++函数源文件中不使用extern "c",编译出来的函数名字也是按照c风格,而不是c++风格,与前面的在cpp中也需要添加extern "c"不一致,留待后面论证。)
c++函数头文件实现:
#ifndef _cpp_h_ #define _cpp_h_ #ifdef __cplusplus extern "C" { #endif void cpp_fun(); #ifdef __cplusplus } #endif #endif
c++函数源文件实现:
#include "cpp.h" extern "C" { //告诉C++编译器,扩号里按照C的命名规则编译 void cpp_fun() { }}
在c中调用c++函数,example.c调用cpp_fun函数:
//example.c实现 #include "cpp.h" int main() { cpp_fun(); return 0; }
上述方案只适合调用C++中的非成员函数,如果你想要在 C 里调用成员函数(包括虚函数),则需要提供一个简单的包装(wrapper)。具体方案参考如下博文: