delphi_dll文件詳解.doc_第1頁
delphi_dll文件詳解.doc_第2頁
delphi_dll文件詳解.doc_第3頁
delphi_dll文件詳解.doc_第4頁
delphi_dll文件詳解.doc_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

非本人原創(chuàng),從其他網絡上下載而來的一、DLL動態(tài)鏈接庫文件的知識簡介: Windows的發(fā)展要求允許同時運行的幾個程序共享一組函數的單一拷貝。動態(tài)鏈接庫就是在這種情況下出現的。動態(tài)鏈接庫不用重復編譯或鏈接,一旦裝入內存,Dlls函數可以被系統(tǒng)中的任何正在運行的應用程序軟件所使用,而不必再將DLLs函數的另一拷貝裝入內存。任何應用程序都可以共享由裝入內存的DLLs管理的內存資源塊。只包含共享數據的DLLs稱為資源文件。在Delphi中,一般工程文件的頭標用program關鍵字,而DLLs工程文件頭標用library 關鍵字標識(ActiveX控件也是一樣)。不同的關鍵字通知編譯器生成不同的可執(zhí)行文件。用program關鍵字生成的是.exe文件,而用library關鍵字生成的是.dll等其他文件;假如要輸出供其它應用程序使用的函數或過程,則必須將這些函數或過程列在Exports子句中。而這些函數或過程本身必須用export編譯指令進行編譯。、使用DLL動態(tài)鏈接庫技術主要有以下幾個原因:1、減少可執(zhí)行文件的大??;2、實現資源共享;3、便于維護和升級4、比較安全二、DLL動態(tài)鏈接庫文件的分類:根據DLLs完成的功能,我們把DLLs分為如下的三類:1、完成一般功能的DLLs;2、用于數據交換的DLLs;3、用于窗體重用的DLLs。三、DLL動態(tài)鏈接庫文件的基本格式如下:library Project1; / 定義DLL文件的文件名,也是庫名。和Unit差不多,會隨保存時的文件名一起改變uses SysUtils, Classes, Unit1 in Unit1.pas Form1, / 創(chuàng)建的窗體文件 Unit2 in Unit2.pas; / 創(chuàng)建的單元文件Type / 定義自己的數據類型Var / 定義變量。 / 自己定義的函數function TestDll(i:integer):integer;stdcall; / 與平時的編寫差不多,只是多了一個stdcall參數begin Result := i+i; end; $R *.res / 設置版本信息Project|options,必須有$R *.res才能顯示。也可以位于函數的定義之前。 / 自己定義的函數exports / 將函數或過程輸出,供其他程序使用。不用寫參數和調用后綴。函數直接用,分開; TestDll; begin end. 四、創(chuàng)建和調用DLL動態(tài)鏈接庫的基本步驟:1、點擊【File】【New】【Other】菜單項,打開【New Items】,選擇【New】;2、選擇【DllWizard】選項卡,點擊ok,DLL工程創(chuàng)建成功。3、添加代碼。4、按【Project】的【Build Project1】生成DLL動態(tài)鏈接庫文件Project1.DLL。5、調用DLL動態(tài)鏈接庫文件。 /調用程序和Project1.dll在同一個目錄中,在implementation下面寫, external后指定了Delphi.dll的位置1、function TestDll(i:integer):integer;stdcall; external Project1.dll; /TestDll 必須跟Dll中函數名一樣,區(qū)分大小寫;Project1不區(qū)分大小寫; 2、使用就跟普通的函數是一樣的。 五、編寫DLL動態(tài)鏈接庫時,應該注意的事項:1、在DLL中編寫的函數或過程都必須加上stdcall調用參數。 在Delphi 1或Delphi 2環(huán)境下該調用參數是far。從Delphi 3以后將這個參數變?yōu)榱藄tdcall,目的是為了使用標準的Win32參數傳遞技術來代替優(yōu)化的register參數。忘記使用stdcall參數是常見的錯誤,這個錯誤不會影響DLL的編譯和生成,但當調用這個DLL時會發(fā)生很嚴重的錯誤,導致操作系統(tǒng)的死鎖。原因是register參數是Delphi的默認參數。如果確實,就會變成register了。2、所寫的函數和過程應該用exports語句聲明為外部函數。 正如大家看到的,TestDll函數被聲明為一個外部函數。這樣做可以使該函數在外部就能看到,具體方法是單激鼠標右鍵用“快速查看(Quick View)”功能查看該DLL文件。(如果沒有“快速查看”選項可以從Windows CD上安裝。)TestDll函數會出現在Export Table欄中。另一個很充分的理由是,如果不這樣聲明,我們如果不這樣聲明,我們編寫的函數將不能被調用,這是大家都不愿看到的。 3、當使用了長字符串類型的參數、變量時要引用ShareMem,或者避免使用String類型。 Delphi中的string類型很強大,我們知道普通的字符串長度最大為256個字符,但Delphi中string類型在默認情況下長度可以達到2G。(對,您沒有看錯,確實是兩兆。)這時,如果您堅持要使用string類型的參數、變量甚至是記錄信息時,就要引用ShareMem單元,而且必須是第一個引用的。既在uses語句后是第一個引用的單元。如下例:uses ShareMem, SysUtils, Classes; 還有一點,在您的工程文件(*.dpr)中而不是單元文件(*.pas)中也要做同樣的工作,這一點Delphi自帶的幫助文件沒有說清楚,造成了很多誤會。不這樣做的話,您很有可能付出死機的代價? 避免使用string類型的方法是將string類型的參數、變量等聲明為Pchar或ShortString(如:s:string10)類型。同樣的問題會出現在當您使用了動態(tài)數組時,解決的方法同上所述。 六、在Delphi中調用DLL: 在Delphi中調用DLL動態(tài)鏈接庫有兩種方法:靜態(tài)調用方法、動態(tài)調用方法;1、靜態(tài)調用DLL動態(tài)鏈接庫(如上面給出的格式一樣)unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TForm1 = class(TForm) Edit1: TEdit; / 編輯框(Edit)Button1: TButton; / 按鈕(Button)procedure Button1Click(Sender: TObject); private Private declarations public Public declarations end; var Form1: TForm1; implementation $R *.DFM / 本行以下代碼為我們真正動手寫的代碼 function TestDll(i:integer):integer;stdcall; external Project1.dll ; procedure TForm1.Button1Click(Sender: TObject); begin Edit1.Text:=IntToStr(TestDll(1); end; end. 注意事項有以下一些: 1、調用參數用stdcall。 和前面提到的一樣,當引用DLL中的函數和過程時也要使用stdcall參數,原因和前面提到的一樣。 2、用external語句指定被調用的DLL文件的路徑和名稱。 正如大家看到的,我們在external語句中指定了所要調用的DLL文件的名稱。沒有寫路徑是因為該DLL文件和調用它的主程序在同一目錄下。如果DLL文件在C:,則我們可將上面的引用語句寫為external C:Delphi.dll 。注意文件的后綴.dll必須寫上。 3、不能從DLL中調用全局變量。 如果我們在DLL中聲明了某種全局變量,如:var s:byte。這樣在DLL中s這個全局變量是可以正常使用的,但s不能被調用程序使用,既s不能作為全局變量傳遞給調用程序。不過在調用程序中聲明的變量可以作為參數傳遞給DLL。 4、被調用的DLL必須存在。 這一點很重要,使用靜態(tài)調用方法時要求所調用的DLL文件以及要調用的函數或過程等等必須存在。如果不存在或指定的路徑和文件名不正確的話,運行主程序時系統(tǒng)會提示“啟動程序時出錯”或“找不到*.dll文件”等運行錯誤。 2、動態(tài)調用DLL動態(tài)鏈接庫只是將原來的Button1Click過程中的語句用下面的代碼替換掉了。 procedure TForm1.Button1Click(Sender: TObject); type TIntFunc=function(i:integer):integer;stdcall; /定義一個函數類型var Th: Thandle; Tf: TIntFunc; Tp: TFarProc; begin Th := LoadLibrary( Project1.dll); / 裝載DLL文件 if Th0 then try Tp:=GetProcAddress(Th,PChar(TestDll); / 查找函數的位置if Tpnil then begin Tf := TIntFunc(Tp); Edit1.Text := IntToStr(Tf(1); / 調用TestC函數 end else ShowMessage(TestDll函數沒有找到 ); Finally FreeLibrary(Th); / 釋放DLL,否則會一直占用內存,知道退出windows或關機為止; End else ShowMessage( Project1.dll沒有找到 ); end; 大家已經看到了,這種動態(tài)調用技術很復雜,但只要修改參數,如修改LoadLibrary( Project1.dll )中的DLL名稱為Delphi.dll 就可動態(tài)更改所調用的DLL。 注意的事項有以下:1、定義所要調用的函數或過程的類型。 在上面的代碼中我們定義了一個TIntFunc類型,這是對應我們將要調用的函數TestDll的。在其他調用情況下也要做同樣的定義工作。并且也要加上stdcall調用參數。 2、釋放所調用的DLL。 我們用LoadLibrary動態(tài)的調用了一個DLL,但要記住必須在使用完后手動地用FreeLibrary將該DLL釋放掉,否則該DLL將一直占用內存直到您退出Windows或關機為止。3、兩種調用方法之間的優(yōu)缺點: 靜態(tài)方法實現簡單,易于掌握并且一般來說稍微快一點,也更加安全可靠一些;但是靜態(tài)方法不能靈活地在運行時裝卸所需的DLL,而是在主程序開始運行時就裝載指定的DLL直到程序結束時才釋放該DLL,另外只有基于編譯器和鏈接器的系統(tǒng)(如Delphi)才可以使用該方法。 動態(tài)方法較好地解決了靜態(tài)方法中存在的不足,可以方便地訪問DLL中的函數和過程,甚至一些老版本DLL中新添加的函數或過程;但動態(tài)方法難以完全掌握,使用時因為不同的函數或過程要定義很多很復雜的類型和調用方法。對于初學者,筆者建議您使用靜態(tài)方法,待熟練后再使用動態(tài)調用方法。 七、使用DLL的實用技巧:1、編寫技巧: 1、為了保證DLL的正確性,可先編寫成普通的應用程序的一部分,調試無誤后再從主程序中分離出來,編譯成DLL。2、為了保證DLL的通用性,應該在自己編寫的DLL中杜絕出現可視化控件的名稱,如:Edit1.Text中的Edit1名稱;或者自定義非Windows定義的類型,如某種記錄。 3、為便于調試,每個函數和過程應該盡可能短小精悍,并配合具體詳細的注釋。 4、應多利用try-finally來處理可能出現的錯誤和異常,注意這時要引用SysUtils單元。5、盡可能少引用單元以減小DLL的大小,特別是不要引用可視化單元,如Dialogs單元。例如一般情況下,我們可以不 引用Classes單元,這樣可使編譯后的DLL減小大約16Kb。 2、調用技巧:1、在用靜態(tài)方法時,可以給被調用的函數或過程更名。改寫引用函數為 function TestC(i:integer):integer;stdcall; external Project1.dll name TestDll ; 其中name的作用就是重命名(原名稱仍然大小寫敏感)。 直接通過名稱調用(注意名稱大小寫敏感)。 function TestDll (i:integer):integer;stdcall; external Project1.dll ; / 如果定義了Index就可以使用,通過索引號調用。程序中可以用與DLL中不一樣的名稱. procedure test2;external Project1.dll index 1;/ exports TestDll index 1;2、可把我們編寫的DLL放到Windows目錄下或者Windowssystem目錄下。這樣做可以在external語句中或LoadLibrary語句中不寫路徑而只寫DLL的名稱。但這樣做有些不妥,這兩個目錄下有大量重要的系統(tǒng)DLL,如果您編的DLL與 它們重名的話其后果簡直不堪設想.3、調試技巧:1、我們知道DLL在編寫時是不能運行和單步調試的。有一個辦法可以,那就是在Run|parameters菜單中設置一個宿 主程序。在Local頁的Host Application欄中添上宿主程序的名字。宿主程序是使用它生成的DLL包的程序。然后 再DLL工程中點擊【Run】就可進行單步調試、斷點觀察和運行了。 2、添加DLL的版本信息。如果包含了版本信息,DLL的大小會增加2Kb。增加這么一點空間是值得的。很不幸我們如 果直接使用Project|options菜單中Version選項是不行的,還必須增加$R *.res,才會顯示版本信息;3、為了避免與別的DLL重名,在給自己編寫的DLL起名字的時候最好采用字符數字和下劃線混合的方式。如:jl_try16.dll。八、具體的一個例子:用DLL文件封裝窗體的實現方法實例: 一個程序不再是單一的一個EXE文件了,而是由一個EXE文件加N個DLL文件組成,這樣做的原因是方便以后的維護與更新,也是跨平臺開發(fā)的重要一步。1、打開DELPHI,新建一個DllWizard2、在新建的Dll里新建一個Form3、在新建的Form里usesstdctrls4、在var下面寫:Proceduresynapp(App:THandle);stdcall; Procedureshowform;stdcall;5、然后在implementation下面usesmath6、在$R*.dfm下面寫Proceduresynapp(App:THandle);stdcall;BeginApplication.Handle:=app;/ 防止每顯示一個窗體,就在任務欄中顯示一個圖標End;Procedureshowform;stdcall;BeginForm1

溫馨提示

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

評論

0/150

提交評論