在C中調用C++函數(非成員函數)
如果我們的C++函數有個C連接符(extern “C”),它可以被C編譯器編譯過的C函數直接調用。被C連接符聲明過的C++函數可以擁有C++的一切特徵,但是如果我們想在C中調用這個函數,他的參數和返回值必須能被C所支持。例如,一個函數的形參是和IOstream有關的類,那麼很遺憾,這就沒什麼(簡單的)辦法去讓C編譯器明白這是什麼玩意,也就不能被編譯通過了。C不支持C++中的類、模板和references這些特徵。
這是一個有C連接符聲明的C++函數:
#include <iostream>
extern "C" int print(int i, double d)
{
std::cout << "i = " << i << ", d = " << d;
}
我們可以在C和C++共享的頭文件中聲明如下的一個print函數
#ifdef __cplusplus
extern "C"
#endif
int print(int i, double d);
對於重載的函數,我們最多隻能用extern “C”聲明其中的一個,因爲同一個名字只能當作一個C函數,我們可以像下面的例子這樣在C++中做一下包裝來解決這個問題:
int g(int);
double g(double);
extern "C" int g_int(int i) { return g(i); }
extern "C" double g_double(double d) { return g(d); }
然後C中的包裝函數是這樣的:
int g_int(int);
double g_double(double);
我們也必須在用模板的時候對模板函數做一下包裝,因爲模板函數不能被extern “C”聲明,例子如下:
template<class T> T foo(T t) { ... }
extern "C" int foo_of_int(int t) { return foo(t); }
extern "C" char* foo_of_charp(char* p) { return foo(p); }
小結一下,C++的代碼該調用重載就調用重載,該調用模板調用模板,沒影響,但是C的代碼想調用這兩種函數的話,必須包裝一下。
在C代碼中訪問C++的類和類的成員函數
Q:我們可以在C代碼中訪問C++的類嗎?
A:或許我們可以在C中聲明一個和C++很像的結構體,然後通過某種方式去調用裏面的函數?
沒錯,這種方法是可行的,雖然這樣做會給代碼的可移植性、和維護上增加一些額外複雜的工作。比如我們C++代碼中做了任何的改變,你必須檢查一下我們的C代碼,有可能也要改變。看下面的例子。
比如現在有一個C++的類:
class M {
public:
virtual int foo(int);
// ...
private:
int i, j;
};
我們不能在我們的C代碼中也添加一個M類,但是可以獲得一個指向M類對象的指針,這很像我們在C中用標準輸入輸出操作文件對象。我們在C++代碼中可以像上面包裝模板一樣再包裝一下類的成員函數,如下:
extern "C" int call_M_foo(M* m, int i) { return m->foo(i); }
C中使用M類的如下:
struct M; /* you can supply only an incomplete declaration */
int call_M_foo(struct M*, int); /* declare the wrapper function */
int f(struct M* p, int j) /* now you can call M::foo */
{ return call_M_foo(p, j); }
原文:http://developers.sun.com/solaris/articles/mixing.html