2011-08-03 28 views
8

假設我有兩個項目。一個是應用程序,另一個是共享庫,其中包含可被不僅僅是該應用程序使用的通用可重用代碼。圍繞共享庫邊界的C++接口設計

我的應用程序使用STL,而我的共享庫也使用STL。這裏的第一個問題是我的共享庫正在使用STL。如果我將STL的新版本構建到我的應用程序中,但由於沒有必要重建我的共享庫,那麼我們將立即出現兼容性問題。

我首先想到解決這個問題是在共享庫類的接口中根本不使用STL。假設我們的庫中有一個函數,它接受一個字符串並對它執行一些操作。我會做的函數原型的樣子:

void DoStuffWithStrings(char const* str); 

代替:

void DoStuffWithStrings(std::string const& str); 

對於字符串這可能將是不同的版本STL之間確定,但不足之處是,我們從std::string去,到char*,然後回到std::string,這看起來會導致性能問題。

將原始類型的裝箱/拆箱推薦給他們的STL同行嗎?當我們嘗試這樣做到std::list時,這變得更糟,因爲實際上沒有「原始類型」,我意識到我們可以輕鬆地通過它,因爲沒有進行某種類型的O(n)或類似的操作。

什麼樣的設計在這種情況下效果最好?每個的優點/缺點是什麼?

回答

3

const char*方法的優點之一是,你的庫也可以從C中調用,因此也可以從C中調用很多其他語言(幾乎所有的東西)。這本身就是一個非常有趣的賣點。但是,如果你編寫和維護兩個庫,並且它們將僅用於C++(比如說未來5年),那麼我不會經歷轉換所有事情的麻煩。 std::string是一回事,std::vectorstd::map不會很好地轉換。除此之外,你有多少次轉向另一個STL實現?在這些情況下,你是否真的'忘記'重建你的共享庫?另外,如果真的需要,你仍然可以在後面編寫/生成C風格的包裝。

結論(偏向於我對這件事的經驗):如果你不需要C,那就用stl去吧。

+0

與C的兼容性不是唯一的擔憂,也不是一個很好的經驗法則恕我直言。正如您所說,如果需求不能保證共享庫將始終由應用程序構建,但完全不被C使用,那麼您仍然需要考慮兼容性問題。 C++擁有非常薄弱的​​共享庫支持(與.NET和C#相比),所以我總是努力保證兼容性在任何可能的情況下都不會成爲問題,無論需求如何。對於'std :: vector'和'std :: map',我認爲我們能做的最好的事情莫過於將它們映射到用戶類型。 –

+0

是的條件應該更像「如果你不需要C並且能夠控制所有庫」。 – stijn

0

許多A.P.I.並且共享庫使用「不透明」或通用指針作爲函數中的參數,以避免版本之間的差異。

// this: 
int MyFunc(char* Param1, int Param2, bool Param3); 

// into this: 
struct MyParams 
{ 
    char* Param1; 
    int Param2; 
    bool Param3; 
} 

// "Params" its really "struct MyParams*" 
int MyFunc(void* Params); 

有時如果一個共享庫函數有幾個參數,它們代替的指針,taht預計的指針陣列或結構或甚至一個類。

這取決於你如何使用你的庫,因爲即使你使用C++,許多庫也可以像普通C一樣使用。

2

當然,標準C++庫應該被視爲C++ ABI的一部分,就像虛擬表格佈局或名稱加密方案一樣。此外,ABI中任何不兼容的更改都可能會影響隱藏的角落案例,而不是std :: vector的佈局。換句話說:如果你打算創建一個C++庫,可以隨意使用標準的C++類。

+0

在什麼樣的例子中,vtables和name mangling scheme會改變?看起來這些變化幾乎不會像STL那樣變化。 –

+0

@Robert如果舊編譯器版本中存在錯誤,或者新編譯器版本支持新版本標準的新語言功能,則需要進行更改。基本上相同的條件適用於標準庫ABI中的更改。沒有很好的理由,沒有人會以不兼容的方式改變標準庫。 – han

+0

因此,例如,如果我從VS8升級到VS9,那會導致不兼容? –

1

如果庫使用與應用程序不同的堆,可能會出現另一個問題。如果是這種情況或可能是這種情況,請確保庫擁有/管理自己的內存。當庫使用不同的c庫,因此不同的malloc/free和不同的堆時,多堆可能會成爲問題。 http://msdn.microsoft.com/en-us/library/ms810466.aspx