C中调用C++,C++中调用C都会用到extern "C",但两者的意义却大不一样!!
先介绍在C++中调用C,这个大家都比较熟悉:
例:
//C代码
<span style="font-family:Microsoft YaHei;font-size:18px;">void foo( int x );
</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">void foo( int x );</span>
//C++代码
<span style="font-family:Microsoft YaHei;font-size:18px;">//C++ code
extern"C"void foo( int x );
</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">//C++ codeextern "C" void foo( int x );</span>让C++连接器能通过过类似于_foo来查找此函数,而非类似于_foo_int这样的符号。
使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。
再来说说C中调用C++,这其中也会用到extern "C",这则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译。
C++代码:(非成员函数)
<span style="font-family:Microsoft YaHei;font-size:18px;">extern"C"int foo( int x );
int foo( int x )
{
//...
}</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">extern "C" int foo( int x );int foo( int x ){//...}</span>这样,编译器会将foo函数编译成类似_foo符号,而不会编译成类似_foo_int符号。
C代码
<span style="font-family:Microsoft YaHei;font-size:18px;">int foo( int x );
void cc( int x )
{
foo( x );
//...
}</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">int foo( int x );void cc( int x ){foo( x );//...}</span>
如果你想要在 C 里调用成员函数(包括虚函数),则需要提供一个简单的包装(wrapper)。例如:
<span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code:
class C
{
// ...
virtualdouble f(int);
};
extern"C"double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code:class C{// ...virtual double f(int);};extern "C" double call_C_f(C* p, int i) // wrapper function{return p->f(i);}</span>
然后,你就可以这样调用 C::f():
<span style="font-family:Microsoft YaHei;font-size:18px;">/* C code: */
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
double d = call_C_f(p,i);
/* ... */
} </span>
<span style="font-family:Microsoft YaHei;font-size:18px;">/* C code: */double call_C_f(struct C* p, int i);void ccc(struct C* p, int i){double d = call_C_f(p,i);/* ... */} </span>
如果你想在 C 里调用重载函数,则必须提供不同名字的包装,这样才能被 C 代码调用。例如:
<span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code:
void f(int);
void f(double);
extern"C"void f_i(int i) { f(i); }
extern"C"void f_d(double d) { f(d); } </span>
<span style="font-family:Microsoft YaHei;font-size:18px;">// C++ code:void f(int);void f(double);extern "C" void f_i(int i) { f(i); }extern "C" void f_d(double d) { f(d); } </span>
然后,你可以这样使用每个重载的 f():
<span style="font-family:Microsoft YaHei;font-size:18px;">/* C code: */
void f_i(int);
void f_d(double);
void cccc(int i,double d)
{
f_i(i);
f_d(d);
/* ... */
} </span>
<span style="font-family:Microsoft YaHei;font-size:18px;">/* C code: */void f_i(int);void f_d(double);void cccc(int i,double d){f_i(i);f_d(d);/* ... */} </span>
参考文献:
Bjarne Stroustrup的原文链接地址是 http://www.research.att.com/~bs/bs_faq2.html#callCpp
下面就一个例子,来介绍一下C调用C++的过程:
<span style="font-family:Microsoft YaHei;font-size:18px;">// cpp.h
#ifndef __cpp_h__
#define __cpp_h__
class class1 {
class1();
~class1();
public:
int I;
int J;
int getI(void);
};
#endif
// end file
// cpp.cpp
#i nclude "stdafx.h"
#i nclude <iostream>
#i nclude "cpp.h"
#i nclude "c.h"
usingnamespace std; // 打开标准库名字空间
class1::class1()
{}
class1::~class1()
{}
int class1::getI(void)
{
return I++;
}
// 按 C 调用方式编译下面函数
extern"C"
int get_class1_I(struct1 * p)
{
class1 * pClass1 = (class1 *)p;
cout << "c++: " << pClass1->getI() << endl;
return pClass1->getI();
}
// end file
// c.h
#ifndef __c_h__
#define __c_h__
#ifdef __cplusplus
extern"C" {
#endif
typedefstruct {
int i; // 与 class1 类中变量一致
int j;
}struct1;
#ifdef __cplusplus
}
#endif
#endif
// end file
// c.c
#i nclude <cstdio>
#i nclude "c.h"
externint get_class1_I(void * p);
struct1 s;
int main(void)
{
printf ("c: %d\n", get_class1_I(&s));
printf ("c: %d\n", get_class1_I(&s));
return 0;
}
// end file</span>
<span style="font-family:Microsoft YaHei;font-size:18px;">// cpp.h#ifndef __cpp_h__#define __cpp_h__class class1 {class1();~class1();public:int I;int J;int getI(void);};#endif// end file// cpp.cpp#i nclude "stdafx.h"#i nclude <iostream>#i nclude "cpp.h"#i nclude "c.h"using namespace std; // 打开标准库名字空间class1::class1(){}class1::~class1(){}int class1::getI(void){return I++;}// 按 C 调用方式编译下面函数extern "C"int get_class1_I(struct1 * p){class1 * pClass1 = (class1 *)p;cout << "c++: " << pClass1->getI() << endl;return pClass1->getI();}// end file// c.h#ifndef __c_h__#define __c_h__#ifdef __cplusplusextern "C" {#endiftypedef struct {int i; // 与 class1 类中变量一致int j;}struct1;#ifdef __cplusplus}#endif#endif// end file// c.c#i nclude <cstdio>#i nclude "c.h"extern int get_class1_I(void * p);struct1 s;int main(void){printf ("c: %d\n", get_class1_I(&s));printf ("c: %d\n", get_class1_I(&s));return 0;}// end file</span>在linux下,执行:
gcc -c c.c
g++ -c cpp.cpp
gcc -lstdc++ c.o cpp.o -o result
转载于:https://blog.51cto.com/yaoyong2012/859248