1. 程式人生 > >VS2013生成、使用dll,lib檔案

VS2013生成、使用dll,lib檔案

一般來說專案偏愛生成dll檔案,具體原因後面會解釋。

什麼是庫

庫是寫好的現有的,成熟的,可以複用的程式碼。現實中每個程式都要依賴很多基礎的底層庫,不可能每個人的程式碼都從零開始,因此庫的存在意義非同尋常

本質上來說庫是一種可執行程式碼的二進位制形式,可以被作業系統載入記憶體執行。庫有兩種:靜態庫(.a、.lib)和動態庫(.so、.dll)。

所謂靜態、動態是指連結。回顧一下,將一個程式編譯成可執行程式的步驟:

靜態庫

之所以稱為【靜態庫】,是因為在連結階段,會將彙編生成的目標檔案.o與引用到的庫一起連結打包到可執行檔案中。因此對應的連結方式稱為靜態連結。

試想一下,靜態庫與彙編生成的目標檔案一起連結為可執行檔案,那麼靜態庫必定跟.o檔案格式相似。其實一個靜態庫可以簡單看成是一組目標檔案(.o/.obj檔案)的集合,即很多目標檔案經過壓縮打包後形成的一個檔案。靜態庫特點總結:

1. 靜態庫對函式庫的連結是放在編譯時期完成的。

2. 程式在執行時與函式庫再無瓜葛,移植方便。

3. 浪費空間和資源,因為所有相關的目標檔案與牽涉到的函式庫被連結合成一個可執行檔案。

Windows下建立與使用靜態庫

建立靜態庫(.lib)

建立win32控制檯程式時,勾選靜態庫型別(下面的預編譯等選項可選可不選);開啟工程“屬性面板”-”配置屬性”-”常規”,配置型別選擇靜態庫。

程式編譯通過後,Build專案即可生成靜態庫。即可生成.lib,輸出欄會顯示出靜態庫的位置。

使用靜態庫

如果將靜態連結庫拷貝到工程目錄下,則可以只進行這一步:“屬性面板”-”配置屬性”- “連結器”-”輸入”,附加依賴庫中輸入靜態庫名StaticLibrary.lib。

如果沒有進行拷貝,則需要將路徑新增到工程中,“屬性面板”-”配置屬性”- “連結器”-”常規”,附加依賴庫目錄中輸入,靜態庫所在目錄;

注意:!!!當我們作為團隊的一個模組,給其他人鏈接庫的時候,除了.lib檔案還要給對方標頭檔案,否則別人將不知道如何呼叫。

動態庫

通過上面的介紹發現靜態庫,容易使用和理解,也達到了程式碼複用的目的,那為什麼還需要動態庫呢?

為什麼還需要動態庫?

為什麼需要動態庫,其實也是靜態庫的特點導致。

1.空間浪費是靜態庫的一個問題。

 

 2.另一個問題是靜態庫對程式的更新、部署和釋出頁會帶來麻煩。如果靜態庫liba.lib更新了,所以使用它的應用程式都需要重新編譯、釋出給使用者(對於玩家來說,可能是一個很小的改動,卻導致整個程式重新下載,全量更新)。

動態庫在程式編譯時並不會被連線到目的碼中,而是在程式執行是才被載入。不同的應用程式如果呼叫相同的庫,那麼在記憶體裡只需要有一份該共享庫的例項,規避了空間浪費問題。動態庫在程式執行是才被載入,也解決了靜態庫對程式的更新、部署和釋出頁會帶來麻煩。使用者只需要更新動態庫即可,增量更新

 

動態庫特點總結:

1.動態庫把對一些庫函式的連結載入推遲到程式執行的時期。

2.可以實現程序之間的資源共享。(因此動態庫也稱為共享庫)

3.將一些程序升級變得簡單。

4.甚至可以真正做到連結載入完全由程式設計師在程式程式碼中控制(顯示呼叫)。

建立動態庫(.dll)

我們使用vs2013來生成Dll,其實使用其他的版本也是同理如此。步驟如下:單擊“新建專案”,選擇“Win32 專案”,選擇“下一步”,然後到了如下介面:

點選“DLL”,並同時點選“匯出符號”。然後點選“完成”。

 

先看下面這段程式碼:

#ifdef MAKEDLL_EXPORTS
#define MAKEDLL_API __declspec(dllexport)
#else #define MAKEDLL_API __declspec(dllimport) #endif

如果定義了MAKEDLL_EXPORTS,然後我們再定義MAKEDLL_API為__declspec(dllexport),否則我們定義__declspec(dllimport)。前者主要為生成DLL的專案所使用,後者為使用DLL的專案所使用。dllexport 和 dllimport 儲存類特性是 C 和 C++ 語言的 Microsoft 專用擴充套件。可以使用它們從 DLL 中匯出或向其中匯入函式、資料和物件。

值得說明的是:

為什麼要匯出符號呢?

這是因為“匯出符號”,將為我們建立生成DLL的模板。仔細觀察,vs自動為我們建立了匯出變數nMakeDLL,匯出函式fnMakeDLL,匯出類CMakeDLL。如果上面沒有點選“匯出符號”,將不會生成這些。所以為了方便DLL的建立,我們最好還是使用“匯出符號”。

接下來,你可以改寫上面的類和函式,然後點選專案,選擇“生成”即可產生DLL和LIB。為了簡化起見,本例只考慮匯出函式。

修改完成後點選Build專案,在輸出欄顯示dll檔案的生成位置。

有的部落格中會要求生成動態庫需要設定工程屬性,開啟工程“屬性面板”-”配置屬性”-”常規”,配置型別選擇動態庫。但是現在的VS版本在建立專案選擇dll的時候已經自動設定了。

生成的DLL檔案如下圖所示:

這裡可能大家有個疑問,動態庫怎麼還有一個DynamicLibrary.lib檔案?即無論是靜態連結庫還是動態連結庫,最後都有lib檔案,那麼兩者區別是什麼呢?其實,兩個是完全不一樣的東西。

 

StaticLibrary.lib的大小為190KB,DynamicLibrary.lib的大小為3KB,靜態庫對應的lib檔案叫靜態庫,動態庫對應的lib檔案叫【匯入庫】。實際上靜態庫本身就包含了實際執行程式碼、符號表等等,而對於匯入庫而言,其實際的執行程式碼位於動態庫中,匯入庫只包含了地址符號表等,確保程式找到對應函式的一些基本地址資訊

使用動態庫

而在引用一個新的dll時,比如我們採用靜態引用的方法時,我們一般需要dll的.h,.lib和.dll三個檔案,這時我們在新建專案的“屬性”中選擇“C/C++”-》“常規”-》“附加包含目錄”,新增.h的路徑,在“連結器”—》“常規”-》“附加庫目錄”中新增.lib的路徑,同時我們還需要新增.lib的附加依賴項,這時可在“連結器”—》“輸入”—》“附加依賴項”,填寫**.lib ,最後還需要載入dll的路徑,此時有兩種方法最為常見。第一種,我們先直接執行程式,這時會出現一個錯誤,說“缺少什麼dll”,我們只需將此前生成的dll,放在debug或release目錄下,即可編譯通過。第二種方法,直接將dll放在與.cpp同一目錄下,即可編譯通過。或者你也可以放在某一個新建的bin檔案下,然後在專案的“path”中填寫.bin的路徑,如下所示:

填寫路徑時注意,前面的"path=%path%;" 必須有,後面可填寫絕對路徑相對路徑。

另外我們再仔細講講lib的使用。

使用lib庫有兩個方法,一個是直接把lib引到工程目錄下,在需要用到的地方include一下就可以。程式碼是:

#pragma comment(lib, "testCpp.lib")

另外一個方法是直接設定庫路徑,就不用把lib引到工程目錄下了。直接點開工程屬性,在配置屬性-》聯結器-》常規-》附加庫目錄中新增庫

vs2013生成lib4

 

vs2013生成lib5

 

之後確認。

在配置屬性-》聯結器-》輸入-》附加依賴項。如圖填寫

vs2013生成lib6

 

之後確定,執行工程就可以了。

總結一下,我們使用別人的庫時,如果想偷懶的話,將.h,.lib,.dll都放在工程目錄下,最後會發現我們需要在使用dll的main函式中載入上標頭檔案,再像第一種方法一樣,連結lib,就可以直接使用了。可參考檔案:testDLL.zip

但是我更推崇另一種方法,就是我們單獨建立include,bin,lib資料夾,然後將他們分別按照上面的方法連結上。這樣如果要新增的庫比較多時,會更加整齊,可讀。

總的來說;.h,.lib,.dll的新增方法其實各有很多種,其中.h有兩種:

1. 直接放在工程目錄下

2. 建立include資料夾,放在裡面,然後在專案屬性的“C/C++”-》“常規”-》“附加包含目錄”,新增.h路徑即可。

.lib的方法有兩種

1.直接放在工程目錄下

2.建立lib資料夾,放在裡面,然後在專案屬性的“連結器”-》“常規”-》“附加庫目錄”,新增.lib路徑即可。

dll的方法有兩種

1.直接放在工程目錄下

2.建立bin資料夾,放在裡面,然後在專案“環境”中新增bin的路徑(PS:最好不要用這個)

.lib的附加依賴項有2種:

1.在“連結器”——》“輸入”-》“附加依賴項”,填寫lib名稱

2.在main檔案前面,新增語句:

 

#pragma comment(lib, "testCpp.lib")

以上皆可以自由組合。 

最簡單的方法就是全部放進.cpp目錄下,然後將.lib檔案加入連結器-輸入-附加依賴項就可以了。如果覺得有點亂,可以把.h檔案和.lib檔案拿出來放進資料夾,然後按照上面的方法進行設定。



轉載: https://www.cnblogs.com/qinguoyi/p/7257353.html