2011-03-17 37 views
2

我的可執行文件調用了一些我自己編寫的DLL。根據這些DLL使用的第三方C++庫,我無法自由選擇所有DLL的編譯器設置。因此,在一些DLL中,_ITERATOR_DEBUG_LEVEL被設置爲2(在調試版本中默認),但是在我的可執行文件_ITERATOR_DEBUG_LEVEL中,根據嚴重的性能問題,它被設置爲0。如何將C++對象傳遞給具有不同_ITERATOR_DEBUG_LEVEL的DLL

當我現在將std::string傳遞給DLL時,只要DLL嘗試將其複製到本地std :: string obj,應用程序就會崩潰,因爲DLL中字符串對象的內存佈局不同於在我的可執行文件中。到目前爲止,我通過傳遞C字符串來解決這個問題。我甚至寫了一個小類,它將一個std::map<std::string, int>轉換爲C-Data中的臨時表示並將其轉換爲C-Data中的臨時表示,以便將sich數據傳遞給DLL。這工作。

我該如何克服這個問題?我想傳遞更多不同的類和容器,並且由於幾個原因,我不想與_ITERATOR_DEBUG_LEVEL = 2一起工作。

+0

摘要:bye bye OO ... – 2011-03-17 14:15:33

+0

完全沒有 - 沒有stl並不意味着沒有OO。您可以使用不包含數據成員的類來創建抽象接口/適配器 - 只有純虛擬方法。在這裏,我發現了一篇有趣的文章:[代碼項目:從DLL導出C++類](http://www.codeproject.com/KB/cpp/howto_export_cpp_classes.aspx#CppMatureApproach) – MacGucky 2011-03-17 14:37:17

+0

不,作爲客戶,您應該**需求**將第三方庫編譯爲可用版本。或者被允許重新編譯自己。這不是一個語言問題,這是一個業務問題。誰長期出售無法使用的圖書館? – 2011-03-17 14:40:47

回答

2

問題是,std :: string和其他容器是模板類。它們是在編譯時爲每個二進制生成的,所以在你的情況下它們的生成方式不同。你可以說它不是同一個對象。

要解決這個問題,你有幾個解決方案,但他們都遵循相同的經驗法則:不要在你的頭文件代碼中公開任何模板代碼

您只能爲此創建特定的接口,或者只是確保您的頭文件不公開模板類型和函數。您可以在二進制文件中使用這些模板類型,但不要將其暴露給其他二進制文件。

接口中的std :: string可以被const char *替換。您仍然可以在系統中使用std :: string,只需在接口中請求const char *並使用std :: string :: c_str()來公開您的數據。

對於地圖和其他容器,您必須提供允許外部代碼操作內部地圖的函數。像「Find(const char * key);」。

主要問題將與您的暴露類的模板成員。解決這個問題的一個方法是使用PImpl習慣用法:創建(或生成)一個API,頭文件,只是公開可以用你的二進制文件完成的工作,然後確保API指向你的二進制文件中的真實對象。該API將用於外部但在您的庫內部,您可以使用任何您想要的代碼進行編碼。 DirectX API和其他操作系統API以這種方式完成。

+0

如果你的圖書館有類似的來源於? – phandinhlan 2015-06-17 08:33:39

+0

@phandinhlan在這種情況下會出現什麼問題?如果您考慮提供對內部成員的訪問權限,那麼只需使用受保護的訪問者函數將這些成員存儲在impl中。 – Klaim 2015-06-17 12:49:33

2

我對像_SECURE_SCL和_ITERATOR_DEBUG_LEVEL這樣的標誌有自己的經驗,如果您嘗試通過,它們必須一致一個stl對象跨dll badaries。 但是我認爲你可以將一個stl對象傳遞給一個dll,它有一個較小的_ITERATOR_DEBUG_LEVEL ,因爲你可以將一個stl對象在一個調試dll中實例化爲一個在發佈模式下編譯的dll。

編輯07/04/2011 顯然,Visual Studio 2010提供了一些檢測ITERATOR_DEBUG_LEVEL之間不匹配的細節。我還沒有觀看視頻。

http://blogs.msdn.com/b/vcblog/archive/2011/04/05/10150198.aspx

3

不建議使用的C++接口與複雜類型(STL ...)與第三方庫,如果你讓他們只爲二進制或需要它們是從不同的編譯特殊設置你的設置。

正如你寫的 - 實現可能會因同一個編譯器而異,具體取決於你的設置和不同的編譯器,情況會變得更糟。

如果可能的話,用您的編譯器和您的設置編譯第三方庫。

如果這是不可能的,您可以編寫一個包裝器DLL,它使用與第三方庫相同的編譯器和相同的設置進行編譯,併爲您提供一個C-Data接口。在你的項目中,你可以編寫另一個包裝類,這樣你就可以使用STL對象進行函數調用,並將它們轉換並轉換爲「後臺」。