2016-04-18 79 views
6

我讀過以下文章here,它解釋瞭如何從純C代碼調用基於C++的函數。從C代碼調用C++方法

的方法最好用下面的例子說明:

// C++ code: 
class C { 
    // ... 
    virtual double f(int); 
}; 
extern "C" double call_C_f(C* p, int i) // wrapper function 
{ 
    return p->f(i); 
} 

/* 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); 
    /* ... */ 
} 

然而,我不明白如果我在哪裏定義由「P」指出一個實例。請注意,在C代碼中,它是作爲指向不透明結構的指針提供的,並且在C++代碼中它假定爲指向class C的有效實例的指針,但我沒有看到該指針正在被初始化的位置。

p.s. 當然,與不同語言相關的每個代碼塊都用適當的編譯器編譯,並創建不同的目標文件。

回答

6

您需要類似的包裝方法來創建和銷燬C++對象。

C++代碼:

extern "C" C * create_c() 
{ 
    return new C; 
} 

extern "C" void destroy_c(C *p) 
{ 
    delete p; 
} 

C代碼:

// forward declarations (better to put those in a header file) 
struct C; 
struct C * create_c(); 
double call_C_f(struct C* p, int i); 
void destroy_c(struct C *p); 

struct C * p = create_c(); 
double result = call_C_f(p, i); 
destroy_c(p); 
p = NULL; 
+0

這個答案的一個很好的附加功能是關於[POD類型]的一個段落(http://en.cppreference.com/w/cpp/concept/PODType),因爲C類具有虛擬成員函數(防止它成爲POD)是背後需要一個不透明結構的真正原因。 –

+0

感謝您的幫助。但在Usage部分中,我不應該在調用之前先定義函數。定義是從類型'C * create_c()'...但C部分不識別類C. – Zohar81

+2

@ Zohar81只需添加'struct C;'來聲明它 –

0

你會用C++創建它,最有可能的是用new C()。在C中沒有辦法可移植地創建它,所以如果C代碼必須能夠構造新的實例,那麼你必須爲它編寫一個extern "C" C* construct_C();工廠函數;同樣適用於析構函數。

3

在你的例子中,p是你的類C的一個對象。您必須用C++代碼創建它,並將它傳遞給C.

您還應該在C中聲明指向C++類的指針爲void *。類型未知,並且struct C意味着它是已知結構,它是錯的。

例子:

extern "C" { 
struct C; 
struct C *create_c(void) 
{ 
    return new C; 
} 

void destroy_c(struct C *ptr) 
{ 
    delete ((C*)ptr); 
} 
} 
+1

有什麼錯向前聲明'結構C'? –

+1

@BryanChen它確實有效,這不是問題。它只是給人錯誤的印象,你確實知道C代碼中的類型。你不這樣做。這是一種你不知道的不透明類型,因此語義是錯誤的,「void *」具有正確的語義。 – Leandros

+0

我發現實際上有用的結構的使用。由於所有的空指針都是相等的,而不同的結構指針則不相同。 –