2014-07-17 41 views
3

我有用C++編寫的共享庫,它提供了用C++編寫的不同應用程序的一些API調用,現在我想在C程序中使用這個庫。原始庫包含數據類型僅適用於C++等的std :: string和std ::矢量如下:將C程序鏈接到C++共享庫

typedef u_int32_t   ApplicationID; 
typedef std::string   IPAddress; 
typedef std::vector<int> SDLIST; 

這些數據類型被用作輸入參數的API的:

register_client(IPAddress ip); 
export(ApplicationID id, SDLIST *list); 

但在C,我們沒有串也不矢量和這兩個數據類型應修改如下:

typedef char* IPAddress; 
typedef int* SDLIST; 

我試着做下面的變化在我的代碼:

typedef u_int32_t   ApplicationID; 
enter code here 
#ifdef __cplusplus 
    typedef std::string   IPAddress; 
    typedef std::vector<int> SDLIST; 
#else 
    typedef char*    IPAddress; 
    typedef int*    SDLIST; 
#endif 


#ifdef __cplusplus 
extern "C" { 
#endif 

    register_client(IPAddress ip); 
    export(ApplicationID id, SDLIST *list); 

#ifdef __cplusplus 
} 
#endif 

我的問題是:

  1. 這是建立可以在C & C++中使用的庫以正確的方式?

  2. 我的共享庫使用Boost Interprocess庫,它是標準POSIX共享內存調用的包裝。每當我嘗試將此共享庫鏈接到任何應用程序時,我都應該在應用程序中再次包含lrt。所以我的問題是,可以將共享庫靜態鏈接到lrt庫,而無需在所有使用我的共享庫的應用程序中包含lrt

+0

除非你也用C編譯庫,否則包含的頭文件和底層定義將不匹配。相反,將接口更改爲僅可C調用,或者添加一個新的頭文件和函數,用於「包裝」C++代碼並且是可C調用的。 – crashmstr

+0

你爲什麼要用兩種語言寫它?您可以創建一個C庫併爲其編寫C++綁定,或者編寫一個C++庫併爲其編寫C綁定。然後將該圖書館與您的應用程序連接起來,然後瞧。 – maxdev

+0

DLL的導出函數和數據類型應該使用C風格。 – Yuan

回答

3

如果你想要這個工作,你將需要建立一個實現了C的數據類型轉換成C++數據類型一個C API基於C++接口庫。特別是std :: string不是char *,而vector不是int *。

例如,如果API定義了C++功能可按類似

bool CPPAPIFunction(std::string str, std::vector<int> vec) 

你需要實現一個包裝函數(編譯和鏈接,C++),如

int myCMappingFunction(char *cstr, int *carray, int arraylen) 
{ 
    std::string str(cstr); 
    std::vector<int> vec; 
    for (int i =0; i < arraylen; i++) // ... copy C array into C++ vector 
    return (int)CPPFAPIFunction(str, vec); 
} 

也不要忘記在extern「C」塊中聲明你的包裝函數,這樣名稱將會變成C風格而不是C++。

1

讓我一個回答您的問題之一:

  1. 很顯然,這是按照你想混什麼樣的代碼你的使用情況。如果你想提供你的庫應該可以從C和C++調用的功能,你的庫接口應該是C兼容的。查看Using C++ library in C code以獲得如何在C界面中打包C++函數的答案。

  2. 通常建議您不要將自己的庫與所有依賴包打包在一起,因爲它會生成繁重的二進制文件,並且會破壞共享庫的用途,除非您打包的依賴項很小。然而,就你而言,如果你想這樣做,你需要創建靜態共享庫。但是,不可能從兩個共享庫創建。你需要兩個對象文件。請參閱Merge multiple .so shared libraries獲取答案。

+0

感謝您的回答,但對於我的情況,我不希望應用程序瞭解我對共享內存的使用情況,這不是他的擔憂。 – IoT

+0

是的..沒錯。爲此,你需要實現包裝函數來爲你做。例如,您將需要包裝函數來接受和返回C數據類型而不是C++數據類型。 –