資源描述:
《dll靜態(tài)和動(dòng)態(tài)調(diào)用比較》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在行業(yè)資料-天天文庫(kù)。
1、摘要:本文闡述了Windows環(huán)境下動(dòng)態(tài)鏈接庫(kù)的概念和特點(diǎn),對(duì)靜態(tài)調(diào)用和動(dòng)態(tài)調(diào)用兩種調(diào)用方式作出了比較,并給出了Delphi中應(yīng)用動(dòng)態(tài)鏈接庫(kù)的實(shí)例。一、動(dòng)態(tài)鏈接庫(kù)的概念動(dòng)態(tài)鏈接庫(kù)(Dynamic?Link?Library,縮寫(xiě)為DLL)是一個(gè)可以被其它應(yīng)用程序共享的程序模塊,其中封裝了一些可以被共享的例程和資源。動(dòng)態(tài)鏈接庫(kù)文件的擴(kuò)展名一般是dll,也有可能是drv、sys和fon,它和可執(zhí)行文件(exe)非常類(lèi)似,區(qū)別在于DLL中雖然包含了可執(zhí)行代碼卻不能單獨(dú)執(zhí)行,而應(yīng)由Windows應(yīng)用程序直接或間接調(diào)用。動(dòng)態(tài)鏈接是相對(duì)于靜態(tài)鏈接而言的。所謂靜態(tài)鏈接是指把要調(diào)用的函數(shù)或者過(guò)程鏈接到可執(zhí)行文件
2、中,成為可執(zhí)行文件的一部分。換句話說(shuō),函數(shù)和過(guò)程的代碼就在程序的exe文件中,該文件包含了運(yùn)行時(shí)所需的全部代碼。當(dāng)多個(gè)程序都調(diào)用相同函數(shù)時(shí),內(nèi)存中就會(huì)存在這個(gè)函數(shù)的多個(gè)拷貝,這樣就浪費(fèi)了寶貴的內(nèi)存資源。而動(dòng)態(tài)鏈接所調(diào)用的函數(shù)代碼并沒(méi)有被拷貝到應(yīng)用程序的可執(zhí)行文件中去,而是僅僅在其中加入了所調(diào)用函數(shù)的描述信息(往往是一些重定位信息)。僅當(dāng)應(yīng)用程序被裝入內(nèi)存開(kāi)始運(yùn)行時(shí),在Windows的管理下,才在應(yīng)用程序與相應(yīng)的DLL之間建立鏈接關(guān)系。當(dāng)要執(zhí)行所調(diào)用DLL中的函數(shù)時(shí),根據(jù)鏈接產(chǎn)生的重定位信息,Windows才轉(zhuǎn)去執(zhí)行DLL中相應(yīng)的函數(shù)代碼。一般情況下,如果一個(gè)應(yīng)用程序使用了動(dòng)態(tài)鏈接庫(kù),Win32
3、系統(tǒng)保證內(nèi)存中只有DLL的一份復(fù)制品,這是通過(guò)內(nèi)存映射文件實(shí)現(xiàn)的。DLL首先被調(diào)入Win32系統(tǒng)的全局堆棧,然后映射到調(diào)用這個(gè)DLL的進(jìn)程地址空間。在Win32系統(tǒng)中,每個(gè)進(jìn)程擁有自己的32位線性地址空間,如果一個(gè)DLL被多個(gè)進(jìn)程調(diào)用,每個(gè)進(jìn)程都會(huì)收到該DLL的一份映像。與16位Windows不同,在Win32中DLL可以看作是每個(gè)進(jìn)程自己的代碼。二、動(dòng)態(tài)鏈接庫(kù)的優(yōu)點(diǎn)1.?共享代碼、資源和數(shù)據(jù)使用DLL的主要目的就是為了共享代碼,DLL的代碼可以被所有的Windows應(yīng)用程序共享。2.?隱藏實(shí)現(xiàn)的細(xì)節(jié)DLL中的例程可以被應(yīng)用程序訪問(wèn),而應(yīng)用程序并不知道這些例程的細(xì)節(jié)。3.?拓展開(kāi)發(fā)工具如Del
4、phi的功能由于DLL是與語(yǔ)言無(wú)關(guān)的,因此可以創(chuàng)建一個(gè)DLL,被C++、VB或任何支持動(dòng)態(tài)鏈接庫(kù)的語(yǔ)言調(diào)用。這樣如果一種語(yǔ)言存在不足,就可以通過(guò)訪問(wèn)另一種語(yǔ)言創(chuàng)建的DLL來(lái)彌補(bǔ)。三、動(dòng)態(tài)鏈接庫(kù)的實(shí)現(xiàn)方法1.?Load-time?Dynamic?Linking這種用法的前提是在編譯之前已經(jīng)明確知道要調(diào)用DLL中的哪幾個(gè)函數(shù),編譯時(shí)在目標(biāo)文件中只保留必要的鏈接信息,而不含DLL函數(shù)的代碼;當(dāng)程序執(zhí)行時(shí),利用鏈接信息加載DLL函數(shù)代碼并在內(nèi)存中將其鏈接入調(diào)用程序的執(zhí)行空間中,其主要目的是便于代碼共享。2.?Run-time?Dynamic?Linking這種方式是指在編譯之前并不知道將會(huì)調(diào)用哪些DL
5、L函數(shù),完全是在運(yùn)行過(guò)程中根據(jù)需要決定應(yīng)調(diào)用哪個(gè)函數(shù),并用LoadLibrary和GetProcAddress動(dòng)態(tài)獲得DLL函數(shù)的入口地址。?四、DLL的兩種調(diào)用方式在Delphi中的比較編寫(xiě)DLL的目的是為了輸出例程供其他程序調(diào)用,因此在DLL的工程文件中要把輸出的例程用Exports關(guān)鍵字引出。在調(diào)用DLL的應(yīng)用程序中,需要聲明用到的DLL中的方法,聲明格式要和DLL中的聲明一樣。訪問(wèn)DLL中的例程有靜態(tài)調(diào)用和動(dòng)態(tài)調(diào)用兩種方式。靜態(tài)調(diào)用方式就是在單元的Interface部分用External指示字列出要從DLL中引入的例程;動(dòng)態(tài)調(diào)用方式就是通過(guò)調(diào)用Windows的API包括LoadLibr
6、ary函數(shù)、GetProcAddress函數(shù)以及FreeLibrary函數(shù)動(dòng)態(tài)的引入DLL中的例程。靜態(tài)調(diào)用方式所需的代碼較動(dòng)態(tài)調(diào)用方式所需的少,但存在著一些不足,一是如果要加載的DLL不存在或者DLL中沒(méi)有要引入的例程,這時(shí)候程序就自動(dòng)終止運(yùn)行;二是DLL一旦加載就一直駐留在應(yīng)用程序的地址空間,即使DLL已不再需要了。動(dòng)態(tài)調(diào)用方式就可解決以上問(wèn)題,它在需要用到DLL的時(shí)候才通過(guò)LoadLibrary函數(shù)引入,用完后通過(guò)FreeLibrary函數(shù)從內(nèi)存中卸載,而且通過(guò)調(diào)GetProcAddress函數(shù)可以指定不同的例程。最重要的是,如果指定的DLL出錯(cuò),至多是API調(diào)用失敗,不會(huì)導(dǎo)致程序終止。
7、以下將通過(guò)具體的實(shí)例說(shuō)明說(shuō)明這調(diào)用方式的使用方法。1.?靜態(tài)調(diào)用方式示例程序創(chuàng)建了一個(gè)DLL,其中僅包含一個(gè)求兩個(gè)整數(shù)的和的函數(shù),在主程序中輸入兩個(gè)整數(shù),通過(guò)調(diào)用該DLL,即可求出兩個(gè)整數(shù)的和,如圖1所示。圖1?DLL的靜態(tài)調(diào)用該DLL的程序代碼如下:library?AddNum;usesSysUtils,Classes;{$R?*.res}function?AddNumber(Num1,Num2