2016-08-05 162 views
1

我試圖創建一個可以在Windows(VS2015)上讀取多個文件格式的程序(C++)。 爲了做到這一點,我使用Project for MyProgram(這是主程序)和MyLibrary(包含用於不同文件格式的幾個解析器)的項目創建了一個解決方案。 在MyProgram中,我根據程序輸入創建了一些解析器對象。將程序鏈接到靜態庫,將其自身鏈接到另一個庫

一切工作正常。

不過,我試圖創建一個新的文件格式分析器(NiftiParser)使用外部庫,nifticlib,我下載並編譯(靜態庫)。

所以我創建了NiftiParser類,實現一些方法,並在內部,它調用nifticlib。 我在項目屬性中添加了包含目錄和庫目錄,並且編譯時沒有錯誤。 然後我得到了一個已創建的Parser.lib。

然而,當我試圖編譯MyProgram,我得到了關於未解決nifticlib庫的某些功能的錯誤:

1>------ Build started: Project: Parser, Configuration: Debug x64 ------ 
1> nifti_parser.cc 
1> Parser.vcxproj -> C:\Users\Laurent\Documents\C++-build\Projects\Parser\Debug\Parser.lib 
2>------ Build started: Project: MyProgram, Configuration: Debug x64 ------ 
2>Parser.lib(nifti_parser.obj) : error LNK2019: unresolved external symbol nifti_image_read referenced in function "public: __cdecl NiftiParser::NiftiParser(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" ([email protected]@[email protected][email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@Z) 
2>C:\Users\Laurent\Documents\C++-build\Projects\Debug\MyProgram.exe : fatal error LNK1120: 1 unresolved externals 
========== Build: 1 succeeded, 1 failed, 3 up-to-date, 0 skipped ========== 

我不知道明白爲什麼會這樣。我試圖將包含的路徑和nifticlib的庫目錄添加到MyProgram項目,但我仍然有一些問題。

我不知道理解什麼是Visual Studio的(我曾經在Linux上工作)編譯/鏈接過程。

在我看來,如果它是一個靜態庫,和該連接部分只有當我試圖編譯程序本身發生的項目只編譯。 我對不對?

另外,我不確定nifticlib應該鏈接到哪裏。它應該是對Parser.lib(我使用庫的功能)還是直接對程序?

謝謝。

PS:另外我注意到,nifticlib我的安裝目錄僅包含頭文件和.LIB。我是否也需要有.cpp,或者函數是否已經包含在.lib中?好吧,顯然建立一些東西作爲一個靜態庫沒有鏈接到任何東西,所以這可能是爲什麼我沒有得到任何問題編譯Parser.lib,因爲它不鏈接到nifticlib,但MyProgram需要它。 所以我應該只在我的Parser項目中包含nitficlib的dir目錄,並將Parser.lib和nifticlib放入我的MyProgram項目中?

回答

3

Visual Studio的編譯/鏈接與Linux工具鏈中發生的情況沒有多大區別。在製作二進制文件(可執行文件或動態庫)時,必須解析所有外部符號。在GCC中,您必須將鏈接庫指定爲庫。命令行選項-lmath將告訴鏈接器從爲庫搜索設置的路徑之一加載libmath.a,並在構建可執行映像時使用它。

同樣,在VS你不僅需要設置路徑到庫目錄,但是明確表示庫文件中。這通常在項目屬性 - >鏈接器 - >輸入 - >其他依賴關係上完成。請注意,在Windows中,您只需輸入完整的庫名稱(MyLib。LIB),而不是部分之間的lib .A

還要注意的是,在Windows下你不能鏈接到一個動態庫文件(.dll)的二進制文件。您將需要一個導入庫(.lib)。

當您創建一個靜態庫,工具鏈不能解決外部引用。這就是爲什麼你沒有引用nifticlib而編譯好.lib。

至於你應該鏈接nifticlib,這要看情況。如果只有你的MyLibrary會使用nifticlib的函數,那麼將它與靜態庫鏈接起來是明智的。但是,如果有一天您希望直接在MyProgram中使用nifticlib中的某個函數,則鏈接時可能會發生衝突。在這種情況下,只有在構建MyProgram時才需要鏈接nifticlib。

的經驗法則可以制定這樣的:

  • 如果只在MyLibrary是使用nifticlib的標題,鏈接庫中與第三方一個
  • 如果MyProgram還使用nifticlib的標題(並且實際上從它們調用函數),建立MyProgram時最好鏈接nifticlib

這不是一個嚴格的描述,並且有更復雜的情況,但基本是這樣的。

不,你不需要建立你的靜態庫的時候,當你從一個不同的項目鏈接到庫使用的cpp文件。庫.cpp的內容已經以目標代碼的形式包含在靜態lib文件中。

編輯:如果你希望你的靜態庫與外部組件從另一個靜態鏈接庫,你需要去項目屬性 - >圖書館 - >常規 - >附加依賴,並把外部的.lib有

+0

非常感謝你對這個非常完整的答案。我現在應該可以弄清楚了。雖然 還有一個問題,當您將庫添加到輸入 - >附加依賴,你需要指定的完整路徑,或在圖書館的只是名字? – whiteShadow

+0

只是名字。目錄路徑在VC++目錄 - >庫目錄中指定。另外,如果MyLibrary和MyProgram項目都在同一解決方案中,則根本不需要擔心庫目錄。 VS應該能夠正確地計算出它們,包括構建應用程序的不同版本(調試/版本,x86/x64等)時的情況。只需將庫名稱放入依賴項中即可。 –

+0

非常感謝您的幫助。 我覺得VS裏有什麼令我困惑的是,在哪裏放置信息。我並不十分熟悉解決方案,項目等的概念,以及在何處放置庫目錄等。在Linux上,我使用的是命令行或cmake,我覺得這很容易。但由於:d – whiteShadow

相關問題