转载链接:点击打开链接
项目中经常使用C和C++混合编程,那么,在调用对方接口时,总是不可避免地出现问题。为了让双方和谐地工作,就得用到extern "C"。
1 问题
在C++中,为了支持重载机制,在编译时,要对函数的名字进行一些处理,比如加入函数的返回类型等来加以区别;在C中,只是简单的函数名字而已。如函数void func(int i),C++会把它编译成类似_fun_int或_xxx_funIxxx这样的增加了参数类型的符号,这也是C++可以实现重载的原因;C则把该函数编译成类似_fun的符号,C链接器只要找到该函数符号就可以链接成功,它假设参数类型信息是正确的。故而,关键问题是,C和C++在编译时生成函数名字的方式是不同的。
2 方法
extern "C"是C++的特性,是一种链接约定,它并不影响调用函数的定义,即使做了该声明,对函数类型的检查和参数转换仍要遵循C++的标准,而不是C。主要是为了解决C++在调用C函数库时,用C++直接链接就会出现不能识别符号的问题,而用上extern "C"后,告诉C++编译器要以C语言的方式编译和链接函数,即直接使用函数名而不是一个经过处理的函数名。
3 示例
3.1 C++中调用C接口
代码:
-
/***** C头文件c.h *****/
-
-
-
-
-
extern "C" { /*C++编译器才能支持,C编译器不支持*/
-
-
-
void C_fun();
-
-
-
}
-
-
-
-
/***** C源文件c.c *****/
-
#include "c.h"
-
void C_fun()
-
{
-
/*dosomething*/
-
}
-
功能:在文件cpp.cpp中调用文件c.c中的函数C_fun()
-
/****** C++源文件cpp.cpp ******/
-
#include "c.h"
-
int main()
-
{
-
C_fun()
-
}
3.2 C中调用C++接口
代码:
-
/**** C++头文件 cpp.h *****/
-
-
-
-
extern "C" int add( int x, int y );
-
-
-
/**** C++源文件 cpp.cpp *****/
-
#include "cpp.h"
-
int add( int x, int y )
-
{
-
return x + y;
-
}
-
功能:C文件中调用C++的接口
-
/**** C源文件c.c *****/
-
extern int add( int x, int y );
-
int main( int argc, char* argv[])
-
{
-
-
}
3.3 C++中调用C库的函数
代码:
-
/*C库源文件: hello.c*/
-
-
void func()
-
{
-
printf( "hello,world!\n");
-
}
-
/*C++源文件test.cpp中调用C库的函数*/
-
-
-
-
extern "C" { // 告诉编译器下列代码要以C链接约定的模式进行链接
-
-
-
void func();
-
-
-
}
-
-
-
int main()
-
{
-
func();
-
-
return 0;
-
}
3.4 C中调用C++库的函数
1)C++库代码
-
/*C++库源文件hello.cpp*/
-
-
-
void funcpp()
-
{
-
std:: cout << "hello, world" << std:: endl;
-
}
2)中间接口库,对C++库进行二次封装
-
/*中间接口库 mid.cpp*/
-
-
-
void funcpp();
-
-
-
extern "C" { // 即使这是一个C++程序,下列这个函数的实现也要以C约定的风格来搞!
-
-
-
void m_funcpp()
-
{
-
funcpp();
-
}
-
-
-
}
-
3)C通过链接二次接口库调用C++库
-
/*C源文件test.c*/
-
-
-
int main()
-
{
-
m_funcpp();
-
-
return 0;
-
}