動態(tài)鏈接庫、靜態(tài)庫區(qū)別與VS2005項(xiàng)目相關(guān)設(shè)置
一、動態(tài)鏈接庫、靜態(tài)庫區(qū)別
二、VS2005項(xiàng)目相關(guān)設(shè)置
三、#pragma預(yù)處理指令
動態(tài)鏈接庫、靜態(tài)庫區(qū)別
1、動態(tài)鏈接庫(Dynamic Linked Library)
Windows系統(tǒng)平臺上你可以將獨(dú)立的程序模塊創(chuàng)建為較小的DLL(Dynamic Linkable Library)文件,并可對它們單獨(dú)編譯和測試。在運(yùn)行時,只有當(dāng)EXE程序確實(shí)要調(diào)用這些DLL模塊的情況下,系統(tǒng)才會將它們裝載到內(nèi)存空間中。這種方式不僅減少了EXE文件的大小和對內(nèi)存空間的需求,而且使這些DLL模塊可以同時被多個應(yīng)用程序使用。Windows自己就將一些主要的系統(tǒng)功能以DLL模塊的形式實(shí)現(xiàn)。Windows為應(yīng)用程序提供了豐富的函數(shù)調(diào)用,這些函數(shù)調(diào)用都包含在動態(tài)鏈接庫中。其中有3個最重要的DLL,Kernel32.dll,它包含用于管理內(nèi)存、進(jìn)程和線程的各個函數(shù);User32.dll,它包含用于執(zhí)行用戶界面任務(wù)(如窗口的創(chuàng)建和消息的傳送)的各個函數(shù);GDI32.dll,它包含用于畫圖和顯示文本的各個函數(shù)。
在使用動態(tài)鏈接庫的時候,往往提供兩個文件:一個引入庫(Import Library)和一個DLL。引入庫包含被DLL導(dǎo)出的函數(shù)和變量的符號名,DLL包含實(shí)際的函數(shù)和數(shù)據(jù)。在編譯鏈接可執(zhí)行文件時,只需要鏈接引入庫,DLL中的函數(shù)代碼和數(shù)據(jù)并不復(fù)制到可執(zhí)行文件中,在運(yùn)行的時候,再去加載DLL,訪問DLL中導(dǎo)出的函數(shù)。 一個Windows的.EXE文件擁有它使用不同動態(tài)鏈接庫的引用,所使用的函數(shù)即在那里。當(dāng)Windows程序被加載到內(nèi)存中時,程序中的調(diào)用被指向DLL函數(shù)的入口,如果DLL不在內(nèi)存中,系統(tǒng)就將其加載到內(nèi)存中。當(dāng)鏈接Windows程序以產(chǎn)生一個可執(zhí)行文件時,你必須鏈接由編程環(huán)境提供的專門的“導(dǎo)入庫(import library)庫”。這些導(dǎo)入庫包含了動態(tài)鏈接庫名稱和所有Windows函數(shù)調(diào)用的引用信息。鏈接程序使用該信息在.EXE文件中構(gòu)造一個表,當(dāng)加載程序時,Windows使用它將調(diào)用轉(zhuǎn)換為Windows函數(shù)。
2、靜態(tài)庫(Static Library)
函數(shù)和數(shù)據(jù)被編譯進(jìn)一個二進(jìn)制文件(通常擴(kuò)展名為.LIB)。在使用靜態(tài)庫的情況下,在編譯鏈接可執(zhí)行文件時,鏈接器從庫中復(fù)制這些函數(shù)和數(shù)據(jù)并把它們和應(yīng)用程序的其它模塊組合起來創(chuàng)建最終的可執(zhí)行文件(.EXE文件)。
導(dǎo)入庫和靜態(tài)庫的區(qū)別很大,他們實(shí)質(zhì)是不一樣的東西。靜態(tài)庫本身就包含了實(shí)際執(zhí)行代碼、符號表等等,而對于導(dǎo)入庫而言,其實(shí)際的執(zhí)行代碼位于動態(tài)庫中,導(dǎo)入庫只包含了地址符號表等,確保程序找到對應(yīng)函數(shù)的一些基本地址信息。
靜態(tài)鏈接與動態(tài)鏈接:
靜態(tài)鏈接方法:#pragma comment(lib, "test.lib") ,靜態(tài)鏈接的時候,載入代碼就會把程序會用到的動態(tài)代碼或動態(tài)代碼的地址確定下來靜態(tài)庫的鏈接可以使用靜態(tài)鏈接,動態(tài)鏈接庫也可以使用這種方法鏈接導(dǎo)入庫
動態(tài)鏈接方法:LoadLibrary()/GetProcessAddress()和FreeLibrary(),使用這種方式的程序并不在一開始就完成動態(tài)鏈接,而是直到真正調(diào)用動態(tài)庫代碼時,載入程序才計(jì)算(被調(diào)用的那部分)動態(tài)代碼的邏輯地址,然后等到某個時候,程序又需要調(diào)用另外某塊動態(tài)代碼時,載入程序又去計(jì)算這部分代碼的邏輯地址,所以,這種方式使程序初始化時間較短,但運(yùn)行期間的性能比不上靜態(tài)鏈接的程序。
VS2005項(xiàng)目相關(guān)設(shè)置
應(yīng)用程序使用外部庫時需要進(jìn)行加載,兩種庫的加載本質(zhì)上都是一樣:提供功能和功能的定義!vs2005 c++ 項(xiàng)目設(shè)置外部庫方法如下:
1. 添加編譯所需要(依賴)的 lib 文件
在“項(xiàng)目->屬性->配置屬性->連接器->輸入->附加依賴項(xiàng)”里填寫“winsock.lib”,多個 lib 以空格隔開,等同于“#pragma
comment(lib, "*.lib") ”語句。
2. 添加庫(libs)文件目錄
方法 1:項(xiàng)目->屬性->配置屬性->連接器->常規(guī)->附加庫目錄”
方法 2:[菜單]“工具->選項(xiàng)->項(xiàng)目和解決方案->c++ 目錄”,選擇對應(yīng)平臺,然后添加所需“庫文件”目錄
這個設(shè)置類似于設(shè)置環(huán)境變量,主要是為程序設(shè)置搜索的庫目錄,真正進(jìn)行庫加載還需要進(jìn)行第一種設(shè)置!
3. 添加包含(include)文件目錄
方法 1:“項(xiàng)目->屬性->配置屬性->c/c++->常規(guī)->附加包含目錄”
方法 2:[菜單]“工具->選項(xiàng)->項(xiàng)目和解決方案->c++ 目錄”,添加所需“包括文件”目錄
方法2類似于設(shè)置環(huán)境變量。
4. 導(dǎo)入庫(import)
在“項(xiàng)目->屬性->配置屬性->連接器->高級->導(dǎo)入庫”填寫需要生成的導(dǎo)入庫
#pragma預(yù)處理指令
在所有的預(yù)處理指令中,#pragma指令可能是最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動作。#pragma指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機(jī)或操作系統(tǒng)專有的特征。依據(jù)定義,編譯指示是機(jī)器或操作系統(tǒng)專有的,且對于每個編譯器都是不同的。
其格式一般為: #Pragma Para
其中Para 為參數(shù),下面來看一些常用的參數(shù)。
1、message 參數(shù)。 Message 參數(shù)能夠在編譯信息輸出窗口中輸出相應(yīng)的信息,這對于源代碼信息的控制是非常重要的。其使用方法為:
#Pragma message(“消息文本”)
當(dāng)編譯器遇到這條指令時就在編譯輸出窗口中將消息文本打印出來。
2、另一個使用得比較多的pragma參數(shù)是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能夠設(shè)置程序中函數(shù)代碼存放的代碼段,當(dāng)我們開發(fā)驅(qū)動程序的時候就會使用到它。
3、#pragma once (比較常用)
只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實(shí)際上在VC6中就已經(jīng)有了,但是考慮到兼容性并沒有太多的使用它。
#pragma once是編譯相關(guān),就是說這個編譯系統(tǒng)上能用,但在其他編譯系統(tǒng)不一定可以,也就是說移植性差,不過現(xiàn)在基本上已經(jīng)是每個編譯器都有這個定義了。
4、#pragma warning( disable : 4507 34; once : 4385; error : 164 )
等價于:
#pragma warning(disable:4507 34) // 不顯示4507和34號警告信息
#pragma warning(once:4385) // 4385號警告信息僅報告一次
#pragma warning(error:164) // 把164號警告信息作為一個錯誤。
同時這個pragma warning 也支持如下格式:
#pragma warning( push [ ,n ] )
#pragma warning( pop )
這里n代表一個警告等級(1---4)。
#pragma warning( push )保存所有警告信息的現(xiàn)有的警告狀態(tài)。
#pragma warning( push, n)保存所有警告信息的現(xiàn)有的警告狀態(tài),并且把全局警告等級設(shè)定為n。
#pragma warning( pop )向棧中彈出最后一個警告信息,
在入棧和出棧之間所作的一切改動取消。例如:
#pragma warning( push )
#pragma warning( disable : 4705 )
#pragma warning( disable : 4706 )
#pragma warning( disable : 4707 )
//.......
#pragma warning( pop )
在這段代碼的最后,重新保存所有的警告信息(包括4705,4706和4707)。
5、#pragma comment(...)
該指令將一個注釋記錄放入一個對象文件或可執(zhí)行文件中,常用的lib關(guān)鍵字,可以幫我們連入一個庫文件。該指令的格式為
#pragma comment( "comment-type" [, commentstring] )
該指令將一個注釋記錄放入一個對象文件或可執(zhí)行文件中,comment-type(注釋類型):可以指定為五種預(yù)定義的標(biāo)識符的其中一種五種預(yù)定義的標(biāo)識符為:
compiler:將編譯器的版本號和名稱放入目標(biāo)文件中,本條注釋記錄將被編譯器忽略,如果你為該記錄類型提供了commentstring參數(shù),編譯器將會產(chǎn)生一個警告,例如:#pragma comment( compiler )。
exestr:將commentstring參數(shù)放入目標(biāo)文件中,在鏈接的時候這個字符串將被放入到可執(zhí)行文件中,當(dāng)操作系統(tǒng)加載可執(zhí)行文件的時候,該參數(shù)字符串不會被加載到內(nèi)存中.但是,該字符串可以被dumpbin之類的程序查找出并打印出來,你可以用這個標(biāo)識符將版本號碼之類的信息嵌入到可執(zhí)行文件中。
lib:這是一個非常常用的關(guān)鍵字,用來將一個庫文件鏈接到目標(biāo)文件中常用的lib關(guān)鍵字,可以幫我們連入一個庫文件。例如:
#pragma comment(lib, "user32.lib"), 該指令用來將user32.lib庫文件加入到本工程中。
linker:將一個鏈接選項(xiàng)放入目標(biāo)文件中,你可以使用這個指令來代替由命令行傳入的或者在開發(fā)環(huán)境中設(shè)置的鏈接選項(xiàng),你可以設(shè)定/include選項(xiàng)來強(qiáng)制包含某個對象。