动态链接库、静态库区别与VS2005项目相关设置
出處:http://blog.csdn.net/Ocean2006/archive/2010/02/05/5289908.aspx
?
???? 一、動態鏈接庫、靜態庫區別
???? 二、VS2005項目相關設置
???? 三、#pragma預處理指令
?
動態鏈接庫、靜態庫區別
????? 1、動態鏈接庫(Dynamic Linked Library)
????? Windows系統平臺上你可以將獨立的程序模塊創建為較小的DLL(Dynamic Linkable Library)文件,并可對它們單獨編譯和測試。在運行時,只有當EXE程序確實要調用這些DLL模塊的情況下,系統才會將它們裝載到內存空間中。這種方式不僅減少了EXE文件的大小和對內存空間的需求,而且使這些DLL模塊可以同時被多個應用程序使用。Windows自己就將一些主要的系統功能以DLL模塊的形式實現。Windows為應用程序提供了豐富的函數調用,這些函數調用都包含在動態鏈接庫中。其中有3個最重要的DLL,Kernel32.dll,它包含用于管理內存、進程和線程的各個函數;User32.dll,它包含用于執行用戶界面任務(如窗口的創建和消息的傳送)的各個函數;GDI32.dll,它包含用于畫圖和顯示文本的各個函數。
????? 在使用動態鏈接庫的時候,往往提供兩個文件:一個引入庫(Import Library)和一個DLL。引入庫包含被DLL導出的函數和變量的符號名,DLL包含實際的函數和數據。在編譯鏈接可執行文件時,只需要鏈接引入庫,DLL中的函數代碼和數據并不復制到可執行文件中,在運行的時候,再去加載DLL,訪問DLL中導出的函數。 一個Windows的.EXE文件擁有它使用不同動態鏈接庫的引用,所使用的函數即在那里。當Windows程序被加載到內存中時,程序中的調用被指向DLL函數的入口,如果DLL不在內存中,系統就將其加載到內存中。當鏈接Windows程序以產生一個可執行文件時,你必須鏈接由編程環境提供的專門的“導入庫(import library)庫”。這些導入庫包含了動態鏈接庫名稱和所有Windows函數調用的引用信息。鏈接程序使用該信息在.EXE文件中構造一個表,當加載程序時,Windows使用它將調用轉換為Windows函數。
????? 2、靜態庫(Static Library)
????? 函數和數據被編譯進一個二進制文件(通常擴展名為.LIB)。在使用靜態庫的情況下,在編譯鏈接可執行文件時,鏈接器從庫中復制這些函數和數據并把它們和應用程序的其它模塊組合起來創建最終的可執行文件(.EXE文件)。
????? 導入庫和靜態庫的區別很大,他們實質是不一樣的東西。靜態庫本身就包含了實際執行代碼、符號表等等,而對于導入庫而言,其實際的執行代碼位于動態庫中,導入庫只包含了地址符號表等,確保程序找到對應函數的一些基本地址信息。
????? 靜態鏈接與動態鏈接:
????? 靜態鏈接方法:#pragma comment(lib, “test.lib”) ,靜態鏈接的時候,載入代碼就會把程序會用到的動態代碼或動態代碼的地址確定下來靜態庫的鏈接可以使用靜態鏈接,動態鏈接庫也可以使用這種方法鏈接導入庫
????? 動態鏈接方法:LoadLibrary()/GetProcessAddress()和FreeLibrary(),使用這種方式的程序并不在一開始就完成動態鏈接,而是直到真正調用動態庫代碼時,載入程序才計算(被調用的那部分)動態代碼的邏輯地址,然后等到某個時候,程序又需要調用另外某塊動態代碼時,載入程序又去計算這部分代碼的邏輯地址,所以,這種方式使程序初始化時間較短,但運行期間的性能比不上靜態鏈接的程序。
?
VS2005項目相關設置
????? 應用程序使用外部庫時需要進行加載,兩種庫的加載本質上都是一樣:提供功能和功能的定義!vs2005 c++ 項目設置外部庫方法如下:
???? 1. 添加編譯所需要(依賴)的 lib 文件
???????? 在“項目->屬性->配置屬性->連接器->輸入->附加依賴項”里填寫“winsock.lib”,多個 lib 以空格隔開,等同于“#pragma???
???????? comment(lib, “*.lib”) ”語句。
???? 2. 添加庫(libs)文件目錄
???????? 方法 1:項目->屬性->配置屬性->連接器->常規->附加庫目錄”
???????? 方法 2:[菜單]“工具->選項->項目和解決方案->c++ 目錄”,選擇對應平臺,然后添加所需“庫文件”目錄
???????? 這個設置類似于設置環境變量,主要是為程序設置搜索的庫目錄,真正進行庫加載還需要進行第一種設置!
???? 3. 添加包含(include)文件目錄
???????? 方法 1:“項目->屬性->配置屬性->c/c++->常規->附加包含目錄”
???????? 方法 2:[菜單]“工具->選項->項目和解決方案->c++ 目錄”,添加所需“包括文件”目錄
???????? 方法2類似于設置環境變量。
???? 4. 導入庫(import)
???????? 在“項目->屬性->配置屬性->連接器->高級->導入庫”填寫需要生成的導入庫
?
?
#pragma預處理指令
???? 在所有的預處理指令中,#pragma指令可能是最復雜的了,它的作用是設定編譯器的狀態或者是指示編譯器完成一些特定的動作。#pragma指令對每個編譯器給出了一個方法,在保持與C和C++語言完全兼容的情況下,給出主機或操作系統專有的特征。依據定義,編譯指示是機器或操作系統專有的,且對于每個編譯器都是不同的。
其格式一般為: #Pragma Para
其中Para 為參數,下面來看一些常用的參數。
1、message 參數。 Message 參數能夠在編譯信息輸出窗口中輸出相應的信息,這對于源代碼信息的控制是非常重要的。其使用方法為:
#Pragma message(“消息文本”)
當編譯器遇到這條指令時就在編譯輸出窗口中將消息文本打印出來。
2、另一個使用得比較多的pragma參數是code_seg。格式如:
#pragma code_seg( ["section-name"[,"section-class"] ] )
它能夠設置程序中函數代碼存放的代碼段,當我們開發驅動程序的時候就會使用到它。
3、#pragma once (比較常用)
只要在頭文件的最開始加入這條指令就能夠保證頭文件被編譯一次,這條指令實際上在VC6中就已經有了,但是考慮到兼容性并沒有太多的使用它。
#pragma once是編譯相關,就是說這個編譯系統上能用,但在其他編譯系統不一定可以,也就是說移植性差,不過現在基本上已經是每個編譯器都有這個定義了。
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 )保存所有警告信息的現有的警告狀態。
#pragma warning( push, n)保存所有警告信息的現有的警告狀態,并且把全局警告等級設定為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(…)
該指令將一個注釋記錄放入一個對象文件或可執行文件中,常用的lib關鍵字,可以幫我們連入一個庫文件。該指令的格式為
????????? #pragma comment( “comment-type” [, commentstring] )
????? 該指令將一個注釋記錄放入一個對象文件或可執行文件中,comment-type(注釋類型):可以指定為五種預定義的標識符的其中一種五種預定義的標識符為:
????? compiler:將編譯器的版本號和名稱放入目標文件中,本條注釋記錄將被編譯器忽略,如果你為該記錄類型提供了commentstring參數,編譯器將會產生一個警告,例如:#pragma comment( compiler )。
????? exestr:將commentstring參數放入目標文件中,在鏈接的時候這個字符串將被放入到可執行文件中,當操作系統加載可執行文件的時候,該參數字符串不會被加載到內存中.但是,該字符串可以被dumpbin之類的程序查找出并打印出來,你可以用這個標識符將版本號碼之類的信息嵌入到可執行文件中。
????? lib:這是一個非常常用的關鍵字,用來將一個庫文件鏈接到目標文件中常用的lib關鍵字,可以幫我們連入一個庫文件。例如:
????????? #pragma comment(lib, “user32.lib”), 該指令用來將user32.lib庫文件加入到本工程中。
????? linker:將一個鏈接選項放入目標文件中,你可以使用這個指令來代替由命令行傳入的或者在開發環境中設置的鏈接選項,你可以設定/include選項來強制包含某個對象。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的动态链接库、静态库区别与VS2005项目相关设置的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++模板的编译
- 下一篇: SQL注入原理深度解析