2013-05-27 109 views
5

我知道這不是一個項目開發的好方法,但由於我工作的某些原因,我致力於將一些數據結構集成在C++(LRU緩存和哈希映射)中C項目。C代碼與C++數據結構

到目前爲止,我知道有一些方法可以使用extern "C"來調用C++中的C函數,但是從C調用C++對象(方法...)呢?

我使用GCC。

+1

據我所知,你不能。不是沒有爲C++函數提供C封裝,並將對象公開爲結構體/不透明指針。 (而且,在C++中使用指針是「邪惡的」。) – millimoose

回答

6

如果所有的代碼被用C++編譯器編譯應該沒有(或很少)的問題。

如果你的C編譯時使用g ++編譯了C++,那麼你需要在你的類中編寫一個頭文件包裝器,以使C++代碼通過一組函數可見。

例子:

MyClass.h

#ifdef __cplusplus 


class MyClass 
{ 
    public: 
     MyClass() {/*STUFF*/} 
     ~MyClass() {/*STUFF*/} 

     int doStuff(int x, float y) {/*STUFF*/} 
}; 

extern "C" { 
#endif 

/* C Interface to MyClass */ 

void* createMyClass(); 
void destroyMyClass(void* mc); 
int  doStuffMyClass(void* mc, int x, float y); 

#ifdef __cplusplus 
} 
#endif 

源文件

MyClass.cpp

#include "MyClass.h" 

void* createMyClass()   {return reinterpret_cast<void*>(new MyClass);} 
void destroyMyClass(void* mc) {delete reinterpret_cast<MyClass*>(mc);} 

int  doStuffMyClass(void* mc, int x, float y) 
{ 
    return reinterpret_cast<MyClass*>(mc)->doStuff(x,y); 
} 

你的C代碼現在只包含 「MyClass.h」,並使用C功能提供。

MyCFile.c

#include "MyClass.h" 

int main() 
{ 
    void* myClass = createMyClass(); 
    int value = doStuffMyClass(myClass, 5, 6.0); 
    destroyMyClass(myClass); 
} 
+0

+1非常完整的答案! –

6

寫在你的C++接口C包裝。將其編譯爲C++,但確保將您的C接口包含在extern "C"塊中。這個新的界面應該與你的C程序很好地連接,並且讓你可以訪問你的C++代碼。

5

你需要創建一個帶作爲他們的第一個參數一個指向對象C兼容轉發功能。轉發函數將[通常]將第一個參數轉換爲正確的對象類型並調用相應的成員函數。

// Function declaration in header 
extern "C" void function(void *object, int param1, int param2); 

// Function definition in source file 
extern "C" function(void *object, int param1, int param2) 
{ 
    static_cast<Object*>(object)->member_function(param1, param2); 
} 
+0

+1,這個答案就是我正在學習的一個很好的例子。 –

+2

不要忘記在頭文件的'extern「C''附近放置'#ifdef __cplusplus',這樣它們就可以從C中使用,並捕獲C++代碼中可能出現的任何異常(C不喜歡異常。 ..)。另外,不是使用'void *'作爲對象指針,人們可能想要轉發 - 聲明一個虛擬的'struct'以使類型安全性最小化。 – syam