2011-05-18 51 views
3

是否有可能將C++庫封裝到c中?在C中包裝一個C++庫? (不要「extern c」)

我怎麼能這樣做?

是否有任何現有工具?

(需要獲得訪問現有的C++庫,但只有C)

+4

是的。使用'extern「C」'。 ;) – 2011-05-18 15:34:52

+1

爲什麼你不想使用'extern「C」'?這正是它的作用。 – 2011-05-18 15:40:17

+0

我不想使用它,因爲庫已經編譯並且已經存在,我該如何讓extern「C」? – develhevel 2011-05-19 07:23:01

回答

12

您可以在C中編寫面向對象的代碼,因此如果它是一個面向對象的C++庫,可以將它包裝在一個C接口中。但是,這樣做可能非常繁瑣,特別是如果您需要支持繼承,虛擬功能和類似的東西。

如果C++庫使用泛型編程(模板),它可能變得非常多毛(您需要提供模板的所有必需實例),並快速接近它不值得做的地步。

假設它是面向對象的,這裏有一個如何,你可以在C做OO一個基本的素描:

C++類:

class cpp { 
    public: 
    cpp(int i); 
    void f(); 
}; 

C接口:

#ifdef __cplusplus 
extern "C" { 
#endif 
    typedef void* c_handle; 

    c_handle c_create(int i) 
    { 
    return new cpp(i); 
    } 

    void c_f(c_handle hdl) 
    { 
    static_cast<cpp*>(hdl)->f(); 
    } 

    void c_destroy(c_handle hdl) 
    { 
    delete static_cast<cpp*>(hdl); 
    } 
#ifdef __cplusplus 
} 
#endif 

根據您的要求,你可以修改它。例如,如果這將成爲私有C++ API的公共C接口,則將真實指針作爲句柄分發可能會使其易受攻擊。在這種情況下,你將交出基本上是整數的句柄,將指針存儲在句柄到指針映射中,並用查找來替換演員。

函數返回字符串和其他動態大小的資源也可能變得相當複雜。你需要C調用者提供緩衝區,但它不能事先知道它的大小。某些API(如WIn32 API的一部分)允許調用者使用長度爲0的緩衝區調用此函數,在這種情況下,它們會返回所需緩衝區的長度。但是,這樣做可以通過API調用可怕的低效率。 (如果在執行算法後只知道所需緩衝區的長度,則需要執行兩次)。
我過去做過的一件事是發出句柄(類似於上面代碼中的句柄)到內部存儲的字符串並提供一個API來請求所需的緩衝區大小,檢索提供緩衝區的字符串,並銷燬句柄(刪除內部存儲的字符串)。
這是一個真正PITA使用,但這樣是C.

+0

+1,條件是在這種情況下,「可能」通常更接近「很可能」。 – 2011-05-18 15:41:18

+0

sbi,'static_cast'也可以在這裏使用,對吧? – Nawaz 2011-05-18 15:47:40

+0

@Nawaz:我認爲你是對的。謝謝,我會解決它。 – sbi 2011-05-18 15:49:07

3

編寫一個C++包裝,做一個extern c,編譯使用C++,並打電話給你的包裝。

0

如果C++庫被寫入其可與C編譯器有輕微的編輯工作被編譯(諸如改變boolintfalse0true1等),那可以做到。

但並非所有的C++代碼都可以用C封裝。模板是C++中的一個功能,不能被封裝,或者幾乎不可能。

1

(沒有「外部C」)

外部C不僅可以幫助您有一個名字在DLL就像你看到他們。

您可以使用
dumpbin /EXPORTS your.dll
看到與外部C或沒有它的名字會發生什麼。
http://msdn.microsoft.com/en-us/library/c1h23y6c(v=vs.71).aspx

要回答你的問題......這取決於......但它是非常不可能的,你可以使用它沒有包裝。如果這個C++庫只使用一個簡單的函數和類型,你可以使用它。如果這個C++庫使用一個複雜的類結構 - 可能你將無法從C中使用它,而不包裝。這是因爲類的內部可能根據許多條件以不同的方式構造(使用虛擬表或抽象的推理),或者在示例中,複雜的C++庫可能有自己的對象創建機制,因此您必須以它的方式使用它被設計或者你會得到不可預知的行爲)。

所以,我認爲,你必須爲做圓頂包裝做好準備。

這裏是關於包裝C++類的好文章。它是作者講述的將C++類包裝到C#中的文章,但他在第一步使用了C語言。
http://www.codeproject.com/KB/cs/marshalCPPclass.aspx

0

用C++ cpp將它包裝起來,調用該dll文件,並在該文件中創建「extern C」。

+0

你可以添加一個例子來讓你的答案更清晰嗎? – slfan 2016-05-01 10:52:40