C中調用C++,C++中調用C都會用到extern "C",但兩者的意義卻大不一樣!!
先介紹在C++中調用C,這個大家都比較熟悉:
例:
//C代碼
<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>讓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>這樣,編譯器會將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>
如果你想要在C 裡調用成員函數(包括虛函數),則需要提供一個簡單的包裝(wrapper)。例如:
<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>
如果你想在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>
然後,你可以這樣使用每個重載的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>
參考文獻:
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"
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 __cplusplus
extern "C" {
#endif
typedef 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