C中調用C++函數

在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;

}

我們可以在CC++共享的頭文件中聲明如下的一個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

發佈了3 篇原創文章 · 獲贊 4 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章