extern “C”原理,用法以及使用场景-2016.01.05

时间:2021-10-06 15:51:28

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)。具体方案参考如下博文:

C如何调用C++中函数

4 参考资料

http://blog.csdn.net/hxg130435477/article/details/6632954

http://blog.csdn.net/miyunhong/article/details/4589541