2009-07-14 172 views
13

我是C++的新手,有些東西我完全沒有得到。在C#中,如果我想使用外部庫,例如log4net,我只需添加一個對log4net DLL的引用,並且它的成員會自動提供給我(以及IntelliSense中)。我如何在非託管C++中執行此操作?如何在C++中「添加引用」

回答

23

除了.dll以外,庫經常會帶有1)頭文件(.h)和2).lib文件。

頭文件包含在您的代碼中,以便您訪問庫中的類型和函數聲明。

.lib鏈接到您的應用程序中(項目屬性 - >鏈接器 - >輸入,附加依賴項)。

的的.lib文件通常包含簡單的存根自動加載的dll和轉發功能調用它。

如果你沒有的.lib文件,你就不是必須使用LoadLibrary函數來動態加載DLL。

+0

比我的回答更徹底。我還要補充一點,如果你使用的是LoadLibrary,那麼你不能簡單地通過名字來調用函數。你需要做後期綁定。 – 2009-07-14 20:14:25

+1

我看到我再次不完整。 LoadLibrary返回一個可以傳遞給GetProcAddress的句柄,它給你一個真正的指針。你也可以選擇調用FreeLibrary來卸載它。 (我繼續並刪除了我原來的答案。) – 2009-07-14 20:18:06

+0

@Steven:的確,我認爲如果他確實需要使用LoadLibrary,我只會給他一個出發點,而不會陷入(很多)粗陋的細節之中。 – jalf 2009-07-14 20:23:06

0

您需要做的第一件事是#include描述該庫中可用函數的頭文件。

該庫的實際代碼將在2的一個地方:

  1. 靜態庫(.LIB)
  2. 一個DLL文件(.dll)

根據如何庫的代碼是給你的(如.lib文件或.dll),你必須:

  • #pragma comment(lib,「libraryname.lib」)if它是一個.LIB
  • LoadLibrary如果一個.dll

有時包隨附了,你需要鏈接到的.lib文件和.dll文件。在這種情況下,你不需要調用LoadLibrary,你只需要#pragma comment(lib,「libaryfile.lib」),因爲在這種情況下.lib將你鏈接到.dll。

一個非常重要的細節是將DLL放在應用程序可以找到它的地方。 Charles Petzold說:

當Windows需要在運行需要它的程序之前加載DLL模塊時,庫文件必須存儲在包含.EXE程序,當前目錄,Windows系統目錄, Windows目錄或通過MS-DOS環境中的PATH字符串訪問的目錄。 (該目錄中查找的順序。) Programming windows, 5th ed MSDN

我不推薦使用項目屬性菜單鏈接,因爲它並不像看到哪些庫要鏈接到。

See also

+0

這不回答這個問題。 – 2009-07-14 19:27:18

+0

這確實回答了現在的問題,但不正確。正如jalf所指出的那樣,你通常會鏈接到導入庫(使用編譯指示或以其他方式將其添加到lib.exe關閉的命令行中)。使用LoadLibrary是後期綁定的選擇。 – 2009-07-14 20:16:31

4

C++沒有在你想的感庫。它有一個頭文件,你的文件名爲#include,它有一些鏈接器處理的庫,包含編譯後的代碼。您需要將庫(.LIB文件)添加到鏈接器設置。

在Windows上,如果您使用的是一個DLL,理想情況下應該有一個.LIB文件與它一起使用,稱爲DLL的導入庫,然後將該.LIB文件添加到鏈接器設置中。

9

基本概念如下: 庫有兩種類型:static & dynamic。它們之間的區別在於,鏈接構建步驟中的靜態庫將它們的編譯代碼嵌入到可執行文件(或dll)中;動態庫只是嵌入指向函數的指針,以及在程序加載時應該加載一些DLL的指令。這是由鏈接器爲您實現的。

現在你可以決定這兩個,你要使用。 DLL有許多優點和缺點。如果開發一個巨大的應用程序,可能值得考慮使用延遲加載的DLL而不是靜態庫。有些庫只是作爲DLL傳遞給你,你別無選擇。無論如何,初學者最簡單的方法就是使用靜態庫。這會讓你的部署和測試變得更容易,因爲在處理DLL時必須確保它們在運行時被發現(即使在使用調試器時),這涉及到複製一個目錄中的所有內容或處理路徑變量。

通常一個DLL提供商(如果意圖是,你應該能夠處理庫)提供您一個頭文件(S)和包含來電到所需的DLL中的.lib。一些供應商(例如boost)只要求你包含頭文件,並且lib自動鏈接到你的可執行文件(可以通過編譯器prorietary pragma指令來實現)。如果不是這種情況,您必須進入C++項目的項目設置(project properites/Configuration Properties/Linker/Input),並將lib文件名輸入到「Additional Dependencies」行中。 iced.lib iceutild.lib。您也可以在其中放置完全限定的路徑名​​稱。請注意,您必須爲兩種配置(Debug,Release)輸入lib文件名。這是您對靜態庫和Dll的平等操作。 DLL需要一個DLL庫的唯一區別在於你的app-directory或其中一個路徑目錄。

這一步後,如果您嘗試鏈接不兼容的庫,你仍然可能會得到編譯器錯誤。有很多原因,爲什麼他們可能不兼容。但嘗試首先連接這個庫,看看是否有用。如果不是,請在此處再次發佈您的錯誤;)

包含文件(s)被用於包含在您希望使用smth的地方。從lib。只需包含它,編譯器就會知道這些符號必須來自另一個(編譯的)編譯單元(編譯後的cpp-file =>目標文件)或.lib。它會查找並通知您是否找不到所需的符號。

好運,
Ovanes

附:這一開始可能很難,但是當你習慣它時,它會很容易。