Windows的動(dòng)態(tài)鏈接庫(kù)原理_第1頁(yè)
Windows的動(dòng)態(tài)鏈接庫(kù)原理_第2頁(yè)
Windows的動(dòng)態(tài)鏈接庫(kù)原理_第3頁(yè)
Windows的動(dòng)態(tài)鏈接庫(kù)原理_第4頁(yè)
Windows的動(dòng)態(tài)鏈接庫(kù)原理_第5頁(yè)
已閱讀5頁(yè),還剩6頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、包含的目錄。函數(shù)GetWindowDirectory返回這一目錄的路徑; (3Windows系統(tǒng)目錄(包含系統(tǒng)文件如gdi.exe的目錄。函數(shù)GetSystemDirectory返回這一目錄的路徑; (4包含當(dāng)前任務(wù)可執(zhí)行文件的目錄。利用函數(shù)GetModuleFileName可以返回這一目錄的路徑; (5列在PATH環(huán)境變量中的目錄; (6網(wǎng)絡(luò)的映象目錄列表。 如果函數(shù)執(zhí)行成功,則返回裝載庫(kù)模塊的實(shí)例句柄。否則,返回一個(gè)小于HINSTANCE_ERROR的錯(cuò)誤代碼。錯(cuò)誤代碼的意義如下表: 表10.2 Loadlibrary返回錯(cuò)誤代碼的意義 錯(cuò)誤代碼意義 0 系統(tǒng)內(nèi)存不夠,可執(zhí)行文件被破壞或調(diào)

2、用非法 2 文件沒有被發(fā)現(xiàn) 3 路徑?jīng)]有被發(fā)現(xiàn) 5 企圖動(dòng)態(tài)鏈接一個(gè)任務(wù)或者有一個(gè)共享或網(wǎng)絡(luò)保護(hù)錯(cuò) 6 庫(kù)需要為每個(gè)任務(wù)建立分離的數(shù)據(jù)段 8 沒有足夠的內(nèi)存啟動(dòng)應(yīng)用程序 10 Windows版本不正確 11 可執(zhí)行文件非法?;蛘卟皇荳indows應(yīng)用程序,或者在.EXE映 像中有錯(cuò)誤 12 應(yīng)用程序?yàn)橐粋€(gè)不同的操作系統(tǒng)設(shè)計(jì)(如OS/2程序 13 應(yīng)用程序?yàn)镸S DOS4.0設(shè)計(jì) 14 可執(zhí)行文件的類型不知道 15 試圖裝載一個(gè)實(shí)模式應(yīng)用程序(為早期Windows版本設(shè)計(jì) 16 試圖裝載包含可寫的多個(gè)數(shù)據(jù)段的可執(zhí)行文件的第二個(gè)實(shí)例 19 試圖裝載一個(gè)壓縮的可執(zhí)行文件。文件必須被解壓后才能被裝裁

3、20 動(dòng)態(tài)鏈接庫(kù)文件非法 21 應(yīng)用程序需要32位擴(kuò)展 假如在應(yīng)用程序用Loadlibrary調(diào)用某一模塊前,其它應(yīng)用程序已把該模塊裝入內(nèi)存,則Loadlibrary并不會(huì)裝載該模塊的另一實(shí)例,而是使該模塊的“引用計(jì)數(shù)”加1。 2.GetProcAddress:撿取給定模塊中函數(shù)的地址 語法為: function GetProcAddress(Module: THandle; ProcName: PChar: TFarProc; Module包含被調(diào)用的函數(shù)庫(kù)模塊的句柄,這個(gè)值由Loadlibrary返回。如果把Module設(shè)置為nil,則表示要引用當(dāng)前模塊。 ProcName是指向含有函數(shù)名

4、的以nil結(jié)尾的字符串的指針,或者也可以是函數(shù)的次序值。如果ProcName參數(shù)是次序值,則如果該次序值的函數(shù)在模塊中并不存在時(shí),GetProcAddress仍返回一個(gè)非nil的值。這將引起混亂。因此大部分情況下用函數(shù)名是一種更好的選擇。如果用函數(shù)名,則函數(shù)名的拼寫必須與動(dòng)態(tài)鏈接庫(kù)文件E ,將會(huì)使你的應(yīng)用增色不少。 DLL 中的類與普通類沒有什么差別,對(duì)于DLL 的處理,只要記住兩個(gè)要點(diǎn): 1、不能在一端分配內(nèi)存,而在另一端釋放; 2、必須有類的數(shù)據(jù)導(dǎo)出處理,接口中處理的應(yīng)是標(biāo)準(zhǔn)數(shù)據(jù)類型,想在導(dǎo)出函數(shù)中直接處理類只會(huì)增加你的麻煩。 注:可以利用接口處理導(dǎo)出類,但那對(duì) OLE 或許還有用,對(duì)于一

5、般的應(yīng)用,簡(jiǎn)而避之。 下面是一個(gè)例子: DLL: type TMyDLLClass = class private FData: string; public constructor Create; destructor Destroy; override; property Data: string read FData write FData; end; 定義幾個(gè)通用的接口: type TMyDLLOBJ = type Pointer; /定義 DLL 中的通用對(duì)象指針 function CreateMyDLLObj: TMyDLLOBJ; stdcall; /初始化類 function

6、DoneMyDLLObj(OBJ: TMyDLLOBJ; stdcall; /釋放類 然后增加你的導(dǎo)出函數(shù): procedure FetchMyDLLData(OBJ: TMyDLLOBJ; Buffer: PChar; Size: Longint: stdcall; var MyDLLClass: TMyDLLClass; begin MyDLLClass := TMyDLLClass(OBJ; if MyDLLClass <> nil then StrPLCopy(Buffer, MyDLLClass.Data, Size; end; 看出來了嗎,就這么簡(jiǎn)單,而且相當(dāng)可靠。我的

7、應(yīng)用大多采用這種處理方式,在 DLL 中處理數(shù)據(jù)庫(kù),用一個(gè)數(shù)據(jù)記錄來傳遞和處理信息。應(yīng)用程序完全與數(shù)據(jù)庫(kù)分開,要更換數(shù)據(jù)庫(kù)類型,只要更新 DLL,應(yīng)用程序根本不必改動(dòng)!而且不管用什么語言作主應(yīng)用,都可以利用 Delphi 的強(qiáng)大部分(單元結(jié)構(gòu) - 讓你的代碼容易管理;TList - 我用得是最多的一個(gè)類,加載數(shù)據(jù)表;以及 string ,可以使你在處理串時(shí)偷到不少懶.)來使你的應(yīng)用更加容易開發(fā)! 2003-10-31 14:57:37 使用動(dòng)態(tài)鏈接庫(kù)簡(jiǎn)介:本章內(nèi)容: . 究竟什么是D L L . 靜態(tài)鏈接與動(dòng)態(tài)鏈接 . 為什么使用D L L . 創(chuàng)建和使用D L L . 顯示D L L中的模式

8、窗體 . 在D e l p h i應(yīng)用程序中使用D L L . DLL的入口和出口函數(shù) . DLL中的異常 . 回調(diào)函數(shù) . 從D L L中調(diào)用回調(diào)函數(shù) . 在不同的過程中共享D L L數(shù)據(jù) . 引出D L L中的對(duì)象 本章討論了Wi n 3 2動(dòng)態(tài)鏈接庫(kù),也就是D L L。D L L是用來編寫Wi n d o w s應(yīng)用程序的關(guān)鍵組成部分。 本章討論了使用和創(chuàng)建D L L的幾個(gè)方面,它給出了D L L怎樣工作的概述并討論了怎樣創(chuàng)建和使用D L L, 你將學(xué)會(huì)怎樣調(diào)入D L L和鏈接由它們引出的過程和函數(shù)的不同方法。本章還包括回調(diào)函數(shù)的使用并舉例說明在不同調(diào)用進(jìn)程中如何實(shí)現(xiàn)共享數(shù)據(jù)。 1 究竟

9、什么是DLL 動(dòng)態(tài)鏈接庫(kù)是程序模塊,它包括代碼、數(shù)據(jù)或資源,能夠被其他的Wi n d o w s應(yīng)用程序共享。DLL的主要特點(diǎn)之一是應(yīng)用程序可以在運(yùn)行時(shí)調(diào)入代碼執(zhí)行,而不是在編譯時(shí)鏈接代碼,因此,多個(gè)應(yīng)用程序可以共享同一個(gè)D L L的代碼。事實(shí)上,文件Kernel32.dll、User32.dll、GDI32.dll就 函數(shù)鏈接到可執(zhí)行文件中。其中的引用可以在應(yīng)用程序中聲明,但是通常情況下是放在一個(gè)專門的引入(import單后面的字符串就是該DLL的名稱。要使用這個(gè)單元,應(yīng)用程序只需把MaxUnit加到它的uses子句中即可。 當(dāng)這個(gè)程序運(yùn)行時(shí),該DLL就會(huì)自動(dòng)地被調(diào)入內(nèi)存,并且任何需要調(diào)用M

10、ax(的程序都被鏈接到這個(gè)DLL中的Max(函數(shù)。 調(diào)用DLL有兩種方式,這是其中一種,叫隱式調(diào)用,就是讓W(xué)indows在應(yīng)用程序調(diào)入時(shí)自動(dòng)地調(diào) 3 為什么要使用DLL 使用D L L有若干理由,其中有一些前面已經(jīng)提到過了。大體說來,使用動(dòng)態(tài)鏈接庫(kù)可以共享代碼、系統(tǒng)資源,可以隱藏實(shí)現(xiàn)的代碼或底層的系統(tǒng)例程、設(shè)計(jì)自定義控件。下面將分別討論這幾個(gè)方面的內(nèi)容。 3.1 共享代碼、資源和數(shù)據(jù) 在本章節(jié)前面已經(jīng)提到,共享代碼是創(chuàng)建動(dòng)態(tài)鏈接庫(kù)的主要目的所在。但與單元的代碼共享不同,DLL的代碼可以被任何Windows應(yīng)用程序共享,而單元代碼的共享局限于Delphi應(yīng)用程序。 另外,DLL提供了共享資源的途

11、徑,諸如位圖、字體、圖標(biāo)等等這些都可以放到一個(gè)資源文件中,并直接鏈接到應(yīng)用程序。如果把這些資源放到DLL中,那么就可以讓許多應(yīng)用程序使用,而不必在內(nèi)存里重復(fù)裝入這些資源。 這行代碼的意思表明,ClientToSreen(在動(dòng)態(tài)鏈接庫(kù)User32.dll中,它的名稱叫ClientToSreen. 在1 6位的Windows中,DLL有自己的數(shù)據(jù)段,于是,所有要調(diào)用同一個(gè)DLL的應(yīng)用程序能夠訪問同一個(gè)全局變量和靜態(tài)變量。但在Win32系統(tǒng)中,這就不同了。因?yàn)镈LL的映像被映射到每個(gè)進(jìn)程的地址空間,該DLL的所有數(shù)據(jù)屬于映射到的進(jìn)程。值得一說的是,盡管進(jìn)程間不能共享DLL的數(shù)據(jù),但是同一個(gè)進(jìn)程的所有

12、線程可以共享,因?yàn)榫€程是相互獨(dú)立的,所以在訪問某一DLL的全局變量時(shí),務(wù)必小心,防止引起沖突。 但這并不意味著沒有辦法實(shí)現(xiàn)在進(jìn)程間共享一個(gè)DLL的數(shù)據(jù)。一個(gè)技術(shù)可以通過內(nèi)存映射文件的方法在內(nèi)存中創(chuàng)建一個(gè)共享的區(qū)域。一切需調(diào)用D L L的應(yīng)用程序都可以讀這些存儲(chǔ)在內(nèi)存中的共享區(qū)域的數(shù)據(jù)。 3.2 隱藏實(shí)現(xiàn)的細(xì)節(jié) 有些時(shí)候,你可能想隱藏例程實(shí)現(xiàn)的細(xì)節(jié),DLL就可以實(shí)現(xiàn)這一點(diǎn)。不管為何要隱藏你的代碼,DLL可以使函數(shù)被應(yīng)用程序訪問,而其中的代碼細(xì)節(jié)不被顯現(xiàn),你所要做的只是提供別人能訪問DLL的接口。你也許認(rèn)為Delphi的編譯單元(DCU也可以隱藏細(xì)節(jié),但是DCU只適用于Delphi應(yīng)用程序,而且還

13、受版本的局限。而DLL與語言無關(guān),所以,創(chuàng)建的DLL可以被C+、VB或其他任何支持DLL的語言調(diào)用。 Windows單元是Win32 DLL的接口單元。Delphi提供了Win32 API的源文件,其一是Windows單元的源文件windows.pas. 3.3 自定義 控件 自定義控件通常放在DLL中。這些控件不同于Delphi的自定義組件。自定義控件是在Windows下注冊(cè),并且可以在任何Windows開發(fā)環(huán)境中使用。將這些類型的自定義控件加進(jìn)DLL中,是考慮到即使有多個(gè)應(yīng)用程序要使用這些自定義控件,內(nèi)存中也只有該控件的一份實(shí)例。 注意其實(shí)將自定義控件加進(jìn)DLL這種機(jī)制已經(jīng)過時(shí),現(xiàn)在,微軟

14、使用OLE和ActiveX控件,自定義控件已很少見了。 2003-10-31 15:13:22 Delphi環(huán)境中編寫調(diào)用DLL的方法和技巧 第一章 為什么要使用動(dòng)態(tài)鏈接庫(kù)(DLL) 提起DLL您一定不會(huì)陌生,在Windows中有著大量的以DLL為后綴的文件,它們是保證Windows正常運(yùn)行和維護(hù)升級(jí)的重要保證。其實(shí),DLL是一種特殊的可執(zhí)行文件。說它特殊主要是因?yàn)橐话闼疾荒苤苯舆\(yùn)行,需要宿主程序比如*.EXE程序或其他DLL的動(dòng)態(tài)調(diào)用才能夠使用。簡(jiǎn)單的說,在通常情況下DLL是經(jīng)過編譯的函數(shù)和過程的集合。 使用DLL技術(shù)主要有以下幾個(gè)原因: 一、減小可執(zhí)行文件大小。 DLL技術(shù)的產(chǎn)生有很大一

15、部分原因是為了減小可執(zhí)行文件的大小。當(dāng)操作系統(tǒng)進(jìn)入Windows時(shí)代后,其大小已經(jīng)達(dá)到幾十兆乃至幾百兆。試想如果還是使用DOS時(shí)代的單執(zhí)行文件體系的話一個(gè)可執(zhí)行文件的大小可能將達(dá)到數(shù)十兆,這是大家都不能接受的。解決的方法就是采用動(dòng)態(tài)鏈接技術(shù)將一個(gè)大的可執(zhí)行文件分割成許多小的可執(zhí)行程序。 二、實(shí)現(xiàn)資源共享。 這里指的資源共享包括很多方面,最多的是內(nèi)存共享、代碼共享等等。早期的程序員經(jīng)常碰到這樣的事情,在不同的編程任務(wù)中編寫同樣的代碼。這種方法顯然浪費(fèi)了很多時(shí)間,為了解決這個(gè)問題人們編寫了各種各樣的庫(kù)。但由于編程語言和環(huán)境的不同這些庫(kù)一般都不能通用,而且用戶在運(yùn)行程序時(shí)還需要這些庫(kù)才行,極不方便。

16、DLL的出現(xiàn)就像制定了一個(gè)標(biāo)準(zhǔn)一樣,使這些庫(kù)有了統(tǒng)一的規(guī)范。這樣一來,用不同編程語言的程序員可以方便的使用用別的編程語言編寫的DLL。另外,DLL還有一個(gè)突出的特點(diǎn)就是在內(nèi)存中只裝載一次,這一點(diǎn)可以節(jié)省有限的內(nèi)存,而且可以同時(shí)為多個(gè)進(jìn)程服務(wù)。 三、便于維護(hù)和升級(jí)。 細(xì)心的朋友可能發(fā)現(xiàn)有一些DLL文件是有版本說明的。(查看DLL文件的屬性可以看到,但不是每一個(gè)DLL文件都有)這是為了便于維護(hù)和升級(jí)。舉個(gè)例子吧,早期的Win95中有一個(gè)BUG那就是在閏年不能正確顯示2月29日這一天。后來,Microsoft發(fā)布了一個(gè)補(bǔ)丁程序糾正了這個(gè)BUG。值得一提的是,我們并沒有重裝Win95,而是用新版本的D

17、LL代替了舊版本的DLL。(具體是哪一個(gè)DLL文件筆者一時(shí)想不起來了。)另一個(gè)常見的例子是驅(qū)動(dòng)程序的升級(jí)。例 如,著名的DirectX就多次升級(jí),現(xiàn)在已經(jīng)發(fā)展到了6.0版了。更妙的是,當(dāng)我們?cè)噲D安裝較低版本的DLL時(shí),系統(tǒng)會(huì)給我們提示,避免人為的操作錯(cuò)誤。例如我們升級(jí)某硬件的驅(qū)動(dòng)程序時(shí),經(jīng)常碰到Windows提示我們當(dāng)前安裝的驅(qū)動(dòng)程序比原來的驅(qū)動(dòng)程序舊。 四、比較安全。 這里說的安全也包括很多方面。比如,DLL文件遭受病毒的侵害機(jī)率要比普通的EXE文件低很多。另外,由于是動(dòng)態(tài)鏈接的,這給一些從事破壞工作的“高手”們多少帶來了一些反匯編的困難。 第二章 在Delphi中編寫DLL top 說了那

18、么多,總該言歸正傳了。編寫DLL其實(shí)也不是一件十分困難的事,只是要注意一些事項(xiàng)就夠了。為便于說明,我們先舉一個(gè)例子。 library Delphi; uses SysUtils, Classes; function TestDll(i:integer:integer;stdcall; begin Result:=i; end; exports TestDll; begin end. 上面的例子是不是很簡(jiǎn)單?熟悉Delphi的朋友可以看出以上代碼和一般的Delphi程序的編寫基本是相同的,只是在TestDll函數(shù)后多了一個(gè)stdcall參數(shù)并且用exports語句聲明了TestDll函數(shù)。只要編

19、譯上面的代碼,就可以得到一個(gè)名為Delphi.dll的動(dòng)態(tài)鏈接庫(kù)?,F(xiàn)在,讓我們來看看有哪些需要注意的地方。 一、在DLL中編寫的函數(shù)或過程都必須加上stdcall調(diào)用參數(shù)。在Delphi 1或Delphi 2環(huán)境下該調(diào)用參數(shù)是far。從Delphi 3以后將這個(gè)參數(shù)變?yōu)榱藄tdcall,目的是為了使用標(biāo)準(zhǔn)的Win32參數(shù)傳遞技術(shù)來代替優(yōu)化的register參數(shù)。忘記使用stdcall參數(shù)是常見的錯(cuò)誤,這個(gè)錯(cuò)誤不會(huì)影響DLL的編譯和生成,但當(dāng)調(diào)用這個(gè)DLL時(shí)會(huì)發(fā)生很嚴(yán)重的錯(cuò)誤,導(dǎo)致操作系統(tǒng)的死鎖。原因是register參數(shù)是Delphi的默認(rèn)參數(shù)。 二、所寫的函數(shù)和過程應(yīng)該用exports語句聲

20、明為外部函數(shù)。 正如大家看到的,TestDll函數(shù)被聲明為一個(gè)外部函數(shù)。這樣做可以使該函數(shù)在外部就能看到,具體方法是單激鼠標(biāo)右鍵用“快速查看(QuickView)”功能查看該DLL文件。(如果沒有“快速查看”選項(xiàng)可以從Windows CD上安裝。)TestDll函數(shù)會(huì)出現(xiàn)在ExportTable欄中。另一個(gè)很充分的理由是,如果不這樣聲明,我們編寫的函數(shù)將不能被調(diào)用,這是大家都不愿看到的。 三、當(dāng)使用了長(zhǎng)字符串類型的參數(shù)、變量時(shí)要引用ShareMem。 Delphi中的string類型很強(qiáng)大,我們知道普通的字符串長(zhǎng)度最大為256個(gè)字符,但Delphi中string類型在默認(rèn)情況下長(zhǎng)度可以達(dá)到2G

21、。(對(duì),您沒有看錯(cuò),確實(shí)是兩兆。)這時(shí),如果您堅(jiān)持要使用string類型的參數(shù)、變量甚至是記錄信息時(shí),就要引用ShareMem單元,而且必須是第一個(gè)引用的。既在uses語句后是第一個(gè)引用的單元。如下例: uses ShareMem, SysUtils, Classes; 還有一點(diǎn),在您的工程文件 (*.dpr)中而不是單元文件(*.pas)中也要做同樣的工作,這一點(diǎn)Delphi自帶的幫助文件沒有說清楚,造成了很多誤會(huì)。不這樣做的話,您很有可能付出死機(jī)的代價(jià)。避免使用string類型的方法是將string類型的參數(shù)、變量等聲明為Pchar或ShortString(如:s:string10)類型。

22、同樣的問題會(huì)出現(xiàn)在當(dāng)您使用了動(dòng)態(tài)數(shù)組時(shí),解決的方法同上所述。 第三章 在Delphi中靜態(tài)調(diào)用DL 調(diào)用一個(gè)DLL比寫一個(gè)DLL要容易一些。首先給大家介紹的是靜態(tài)調(diào)用方法,稍后將介紹動(dòng)態(tài)調(diào)用方法,并就兩種方法做一個(gè)比較。同樣的,我們先舉一個(gè)靜態(tài)調(diào)用的例子。 unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm Edit1: TEdit; Button1: TButton; pr

23、ocedure Button1Click(Sender: TObject; private Private declarations public Public declarations end; var Form1: TForm1; implementation $R *.DFM /本行以下代碼為我們真正動(dòng)手寫的代碼 function TestDll(i:integer:integer;stdcall; external Delphi.dll; procedure TForm1.Button1Click(Sender: TObject; begin Edit1.Text:=IntToStr(

24、TestDll(1; end; end. 上面的例子中我們?cè)诖绑w上放置了一個(gè)編輯框(Edit)和一個(gè)按鈕(Button),并且書寫了很少的代碼來測(cè)試我們剛剛編寫的Delphi.dll。大家可以看到我們唯一做的工作是將TestDll函數(shù)的說明部分放在了implementation中,并且用external語句指定了Delphi.dll的位置。(本例中調(diào)用程序和Delphi.dll在同一個(gè)目錄中。)讓人興奮的是,我們自己編寫的TestDll函數(shù)很快被Delphi認(rèn)出來了。您可做這樣一個(gè)實(shí)驗(yàn):輸入“TestDll(”,很快Delphi就會(huì)用fly-by提示條提示您應(yīng)該輸入的參數(shù)是什么,就像我們使用D

25、elphi中定義的其他函數(shù)一樣簡(jiǎn)單。注意事項(xiàng)有以下一些: 一、調(diào)用參數(shù)用stdcall。 和前面提到的一樣,當(dāng)引用DLL中的函數(shù)和過程時(shí)也要使用stdcall參數(shù),原因和前面提到的一樣。 二、用external語句指定被調(diào)用的DLL文件的路徑和名稱。 正如大家看到的,我們?cè)趀xternal語句中指定了所要調(diào)用的DLL文件的名稱。沒有寫路徑是因?yàn)樵揇LL文件和調(diào)用它的主程序在同一目錄下。如果該DLL文件在C:,則我們可將上面的引用語句寫為external C:Delphi.dll。注意文件的后綴.dll必須寫上。 三、不能從DLL中調(diào)用全局變量。 如果我們?cè)贒LL中聲明了某種全局變量,如:var

26、 s:byte 。這樣在DLL中s這個(gè)全局變量是可以正常使用的,但s不能被調(diào)用程序使用,既s不能作為全局變量傳遞給調(diào)用程序。不過在調(diào)用程序中聲明的變量可以作為參數(shù)傳遞給DLL。 四、被調(diào)用的DLL必須存在。 這一點(diǎn)很重要,使用靜態(tài)調(diào)用方法時(shí) 要求所調(diào)用的DLL文件以及要調(diào)用的函數(shù)或過程等等必須存在。如果不存在或指定的路徑和文件名不正確的話,運(yùn)行主程序時(shí)系統(tǒng)會(huì)提示“啟動(dòng)程序時(shí)出錯(cuò)”或“找不到*.dll文件”等運(yùn)行錯(cuò)誤。 第四章 在Delphi中動(dòng)態(tài)調(diào)用DLL top 動(dòng)態(tài)調(diào)用DLL相對(duì)復(fù)雜很多,但非常靈活。為了全面的說明該問題,這次我們舉一個(gè)調(diào)用由C+編寫的DLL的例子。首先在C+中編譯下面的D

27、LL源程序。 #include extern ”C” _declspec(dllexport int WINAPI TestC(int i return i; 編譯后生成一個(gè)DLL文件,在這里我們稱該文件為Cpp.dll,該DLL中只有一個(gè)返回整數(shù)類型的函數(shù)TestC。為了方便說明,我們?nèi)匀灰蒙厦娴恼{(diào)用程序,只是將原來的Button1Click過程中的語句用下面的代碼替換掉了。 procedure TForm1.Button1Click(Sender: TObject; type TIntFunc=function(i:integer:integer;stdcall; var Th:Than

28、dle; Tf:TIntFunc; Tp:TFarProc; begin Th:=LoadLibrary(Cpp.dll; 裝載DLL if Th>0 then try Tp:=GetProcAddress(Th,PChar(TestC; if Tp<>nil then begin Tf:=TIntFunc(Tp; Edit1.Text:=IntToStr(Tf(1; 調(diào)用TestC函數(shù) end else ShowMessage(TestC函數(shù)沒有找到; finally FreeLibrary(Th; 釋放DLL end else ShowMessage(Cpp.dll沒有找

29、到; end; 大家已經(jīng)看到了,這種動(dòng)態(tài)調(diào)用技術(shù)很復(fù)雜,但只要修改參數(shù),如修改LoadLibrary(Cpp.dll中的DLL名稱為Delphi.dll就可動(dòng)態(tài)更改所調(diào)用的DLL。 一、定義所要調(diào)用的函數(shù)或過程的類型。 在上面的代碼中我們定義了一個(gè)TIntFunc類型,這是對(duì)應(yīng)我們將要調(diào)用的函數(shù)TestC的。在其他調(diào)用情況下也要做同樣的定義工作。并且也要加上stdcall調(diào)用參數(shù)。 二、釋放所調(diào)用的DLL。 我們用LoadLibrary動(dòng)態(tài)的調(diào)用了一個(gè)DLL,但要記住必須在使用完后手動(dòng)地用FreeLibrary將該DLL釋放掉,否則該DLL將一直占用內(nèi)存直到您退出Windows或關(guān)機(jī)為止。 現(xiàn)

30、在我們來評(píng)價(jià)一下兩種調(diào)用DLL的方法的優(yōu)缺點(diǎn)。靜態(tài)方法實(shí)現(xiàn)簡(jiǎn)單,易于掌握并且一般來說稍微快一點(diǎn),也更加安全可靠一些;但是靜態(tài)方法不能靈活地在運(yùn)行時(shí)裝卸所需的DLL,而是在主程序開始運(yùn)行時(shí)就裝載指定的DLL直到程序結(jié)束時(shí)才釋放該DLL,另外只有基于編譯器和鏈接器的系統(tǒng)(如Delphi)才可以使用該方法。動(dòng)態(tài)方法較好地解決了靜態(tài)方法中存在的不足,可以方便地訪問DLL中的函數(shù)和過程,甚至一些老版本DLL中新添加的函數(shù)或過程;但動(dòng)態(tài)方法難以完全掌握,使用時(shí)因?yàn)椴煌暮瘮?shù)或過程要定義很多很復(fù)雜的類型和調(diào)用方法。對(duì)于初學(xué)者,筆者建議您使用靜態(tài)方法,待熟練后再使用動(dòng)態(tài)調(diào)用方法。 第五章 使用DLL的實(shí)用技巧

31、 top 一、編寫技巧。 1 、為了保證DLL的 正確性,可先編寫成普通的應(yīng)用程序的一部分,調(diào)試無誤后再?gòu)闹鞒绦蛑蟹蛛x出來,編譯成DLL。 2、為了保證DLL的通用性,應(yīng)該在自己編寫的DLL中杜絕出現(xiàn)可視化控件的名稱,如:Edit1.Text中的Edit1名稱;或者自定義非Windows定義的類型,如某種記錄。 3 、為便于調(diào)試,每個(gè)函數(shù)和過程應(yīng)該盡可能短小精悍,并配合具體詳細(xì)的注釋。 4 、應(yīng)多利用try-finally來處理可能出現(xiàn)的錯(cuò)誤和異常,注意這時(shí)要引用SysUtils單元。 5 、盡可能少引用單元以減小DLL的大小,特別是不要引用可視化單元,如Dialogs單元。例如一般情況下,我們可以不引用Classes單元,這樣可使編譯后的DLL減小大約16Kb。 二、調(diào)用技巧。 1 、在用靜態(tài)方法時(shí),可以給被調(diào)用的函數(shù)或過程更名。在前面提到的C+編寫的DLL例子中,如果去掉extern ”C”語句,C+會(huì)編譯出一些奇怪的函數(shù)名,原來的TestC函數(shù)會(huì)被命名為TestC$s等等可笑的怪名字,這是由于C+采用了C+ name

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論