2011-04-22 113 views
2

我知道,如果我鏈接到我的C++程序到使用不同版本的Visual Studio構建的動態庫(DLL),也不會因爲二進制兼容性問題的工作。 (我已經經歷了這與升壓庫和VS 2005年和2008年)C++動態庫編譯/鏈接

但我的問題是:這是真的所有版本的MSVS?這是否也適用於靜態庫(LIB)?這是GCC & Linux的問題嗎?最後如何將VS鏈接到使用MinGW構建的DLL中?

通過除了跨平臺或跨編譯器的方式,爲什麼不能在兩個版本相同的編譯器(VS)的是compatibile?

+0

可能重複http://stackoverflow.com/questions/5728116/can-i-link-object-files-由另一個製作而成的編譯器) – AProgrammer 2011-04-22 16:28:59

+1

據我所知,MS從來沒有通過改變ABI來改變向後兼容性,所以我認爲兼容性問題在這裏是一個紅鯡魚。雖然這並不是說你可能因DLL不兼容而導致['DLL hell'](http://en.wikipedia.org/wiki/DLL_hell)。你也需要看你連接的DLL的類型。如果您的應用程序是多線程調試,則需要鏈接到相應DLL的多線程調試版本。 – 2011-04-22 17:42:28

回答

2

嗨。我知道,如果我將我的C++程序鏈接到使用不同版本的Visual Studio構建的動態庫(DLL),由於二進制兼容性問題,它不起作用。 (我已經體驗過Boost庫和VS 2005和2008)

我不記得曾經看到MS更改過ABI,下面))。

因此,我不認爲這不是Dev Studio中的不兼容性,而是Boost中的變化。
不同版本的boost不是向後兼容的(在二進制中,它們是向後兼容的源)。

但我的問題是:這是真的所有版本的MSVS?

我不相信有一個問題。現在,如果使用不同的標誌,可以使對象文件不兼容。這就是爲什麼調試/發佈二進制文件被構建到單獨的目錄中並與不同版本的標準運行時間鏈接的原因。

這是否也適用於靜態庫(LIB)?

您必須鏈接正確的靜態庫。但是一旦靜態庫存在於你的代碼中,那麼所有已解析的名稱將不會在以後重新解析。

這是GCC & Linux的問題嗎?

是。海灣合作委員會已經在幾次(幾個目的(有些是錯誤的))中逆轉了ABI的兼容性。這不是一個真正的問題,因爲Linux代碼通常作爲源代碼分發,並且在您的平臺上編譯它,它將起作用。

最後如何將VS鏈接到用MinGW構建的DLL?

對不起,我不知道。

順便說一句,除了跨平臺或交叉編譯器,爲什麼同一個編譯器(VS)的兩個版本不兼容?

充分優化的代碼對象可能會被壓縮得更多,因此對齊是不同的。其他編譯器標誌可能會影響與其他二進制對象不兼容的代碼生成方式(改變函數調用方式(堆棧中的所有參數或寄存器中的某些參數))。從技術上講,只有使用完全相同標誌編譯的對象應該連接在一起(從技術上講,它比稍微寬鬆一點,因爲很多標誌不會影響二進制兼容性)。

注意某些庫與多個版本的相同庫以不同方式編譯發佈。你通常在擴展名結尾區分庫。在我上一份工作中,我們使用了以下約定。

libASR.dll // A Sincgle threaded Relase version lib 
libASD.dll // A Single threaded Debug version 
libAMR.dll // A Multi threaded Release version 
libAMD.dll // A Multi threaded Debug version 
的[我可以鏈接一個編譯做出那些由另一人造物的文件嗎?(
+0

「這不是一個真正的問題,因爲Linux代碼通常作爲源代碼發佈」< - 我認爲這些日子不是這樣。大多數人從二進制軟件包安裝軟件。 – 2011-04-22 18:41:45

+0

非常感謝! 所以你說,如果我在VS2010中使用預構建的VS2008 Qt庫,並且它不起作用,那是因爲這些庫是使用不同的標誌/優化構建的,並且它不是VS或其C++的向後兼容性問題運行時庫? – p00ya00 2011-04-22 18:47:03

+1

@TamásSzelei:在大多數系統中,我使用的包管理系統與源代碼不是二進制的。 apt-get例如下載編譯和安裝。正如perl安裝程序等。我確信軟件包是以二進制格式提供的,但我認爲這是例外情況,而不是Linux上的規則。 – 2011-04-22 18:55:16

0

如果構建得當,DLL應該是編程語言和版本中立的。您可以鏈接到與VB,C,C++內置的DLL等

您可以使用dependency walker檢查在DLL導出的函數。

0

要回答你的問題的一部分,GCC/Linux沒有這個問題。至少,不是經常。 libstdC++和glibc是GNU系統上的標準C++/C庫,這些庫的作者會盡力避免破壞兼容性。 glibc幾乎都是向後兼容的,但libstdC++在過去幾次打破ABI,並且可能在未來再次打破ABI。

它是非常與C相比,C++中編寫穩定的ABI很困難,因爲C++中的自動功能會帶走您維護ABI所需的一些控制。特別是當你進入模板和內聯函數時,其中一些代碼被嵌入到應用程序中,而不是保留在共享庫中。這意味着如果不需要重新編譯應用程序,對象的結構就不會改變。

實際上,這在Windows上並不是什麼大事。如果微軟只是讓MSI安裝程序知道如何在安裝需要它們的應用程序時從Windows Update獲取微軟提供的DLL,但是簡單地將可再發行組件添加到InnoSetup生成的安裝程序就足夠了。

+0

我可能是錯的,但MS從來不知道破壞ABI。另一方面GCC已經做了好幾次。這就是OpenSource作爲源代碼發佈的原因。 – 2011-04-22 17:39:47

+0

@Martin - 自3.4(2004)以來,GCC ABI一直沒有變化,而MSVC在每個主要版本中都打破了它的ABI。請參閱[將Visual C++代碼移植到Visual Studio 2005](http://www.devx.com/cplus/10MinuteSolution/28908/1954)。 – aponomarenko 2011-04-22 21:43:29

+0

@ user720860:我沒有看到任何ABI更改,本文是關於將DevStudio與標準C++內聯。如果你編寫非對稱C++,那麼你不應該期望你的代碼是可移植的(更不用說可升級了),所以在那裏沒有太大的意外。 GCC 3.2(變更)3.3(變更)3.4(變更)。 – 2011-04-25 07:33:03