2010-09-11 57 views
2

我有一個框架(在C++中)依賴於一些第三方庫。當我編譯 框架的靜態版本時,不需要額外的依賴關係,也就是說,不需要第三部分庫的lib文件。當我編譯與DLL相同的框架時,現在需要額外的依賴關係,否則我會遇到鏈接錯誤。我可以猜測爲什麼會發生這種情況,但希望得到一個具體的答案/解釋來理解正在發生的事情。沒有額外的依賴關係需要一個LIB,但需要的一個DLL

編輯:只是爲了澄清,我正在開發可以被編譯爲lib並作爲dll然後在(N)使用(可執行的)項目的框架。將框架編譯爲lib並使用第三方庫中的函數時,我不需要額外的依賴關係。但是,現在使用lib文件(即框架)的項目必須包含第三方lib文件。當我將框架編譯爲dll時,它會給我提供鏈接錯誤,除非我指定了框架在技術上依賴的第三方庫。例如:我有幾個從Ogre3D內部調用功能的類。這些類被編譯爲lib文件。編譯類lib時,我不需要鏈接OgreMain.lib。另一方面,當我編譯同一類的dll版本時,我現在需要鏈接到OgreMain.lib

+0

你是什麼意思附加的依賴? – 2010-09-11 15:49:32

+0

也許我在誤讀某些東西,但我認爲Samaursa在編譯時特別要求這種情況,而不是要求確定運行時依賴關係。這聽起來像他有兩個配置的項目,「構建爲DLL」和「構建爲靜態DLL」。 – Dave 2010-09-11 17:04:28

+0

這是正確的戴夫 – Samaursa 2010-09-11 20:24:00

回答

3

當您有一個靜態庫(一個.lib文件)時,它只是一個或多個目標文件(.obj),鏈接器只是將該代碼添加到您的一個可執行文件中。您可以通過命令行開關,IDE配置設置或甚至是#pragma(具體取決於您的環境和編譯器)告訴鏈接器。

當你鏈接一個DLL時,你需要給鏈接器一些代碼來調用當你調用一個DLL函數。通常,這是通過與.dll具有相同名稱的文件完成的,除了它是.lib。該.lib中的代碼以與上述相同的方式鏈接到您的程序中,但是當您調用它時,會加載DLL(如果尚未加載),然後調用正確的函數。

還有其他方法可以處理DLL鏈接(例如,.def文件或.NET中的#using語句),但這似乎就是您所談論的。


在回答你的問題澄清:

的問題是,是的.lib不是最終產品。它只是一個目標代碼的集合,稍後當鏈接器將所有函數調用連接到函數地址時,它們將被使用。

另一方面,DLL是最終產品,因此鏈接器要求將所有函數和變量連接到實際地址。

我說得有點不準確,但你明白了。

+0

這不完全準確。 DLL/Lib風格的鏈接比.def文件和GetProcAddress更快。無論如何,我都贊成你,但只是爲了迂腐,他們絕對不一樣。例如,與.def文件相比,您可以使用__declspec鏈接成員函數和更多。 – Puppy 2010-09-11 15:28:21

+0

謝謝你的解釋。這清除了可執行項​​目中Lib和DLL鏈接的概念。在一個將被編譯爲'lib'文件或'dll'的框架的情況下,我仍然不完全明白爲什麼我不需要在lib的''附加依賴項'中有任何第三部分'lib'。我的框架編譯,而我需要「附加依賴」中的所有第三方'lib'文件來編譯同一個框架的'dll'版本。 – Samaursa 2010-09-11 20:35:42

+0

根據您的問題澄清更新。 – metal 2010-09-13 20:33:17

0

靜態庫可以包括其它靜態庫,提供了一個單一的lib鏈接

甲DLL可包括靜態庫,提供了一個單個DLL鏈接。

對其他DLL有依賴關係的DLL或靜態庫沒有辦法將它們組合起來,因此您的可執行文件必須顯式鏈接到其他DLL。

0

當您鏈接到一個LIB時,它會將您實際使用的所有符號/函數添加到您的可執行文件中。你不使用的那些不會被添加。當你鏈接到一個DLL - 來自外部庫的所有代碼被加載。如果這個額外的代碼(你不使用的代碼)依賴於更多的外部庫,你也需要提供這些代碼。

舉一個例子:你想從網絡庫中使用一個ip類。 ip類不依賴於其他庫。網絡庫中的其他功能取決於其他外部庫。如果您將網絡庫作爲LIB鏈接,則只需鏈接ip類 - >您不需要其他庫,因爲其他代碼不會鏈接。當你使用DLL時,需要實例化DLL中的所有代碼 - >所以你需要提供其他的外部庫。

0

構建DLL更像是構建應用程序而不是庫。構建一個應用程序和一個DLL之間的區別是什麼可能被稱爲知識。在應用程序中,所有未使用的符號都可以在構建中被丟棄,但是在DLL中,您不能剝離未使用的符號 - 這將是所有這些符號... 您會在靜態庫中發現相同的鏈接問題如果你能夠調用DLL鏈接的所有符號。

相關問題