當前位置:菜譜大全網 - 美食做法 - DELPHI基礎教程:動態鏈接庫編程(1) [1]

DELPHI基礎教程:動態鏈接庫編程(1) [1]

Windows中動態鏈接庫的原理

動態鏈接庫是從C語言函數庫和Pascal庫單元的概念發展而來的。所有C語言標準庫函數都存儲在壹個函數庫中,用戶也可以用LIB程序創建自己的函數庫。在鏈接應用程序的過程中,鏈接器從庫文件中復制程序調用的函數代碼,並添加到可執行文件中。這種方法比僅僅將函數存儲在編譯後的OBJ文件中更有利於代碼重用。

但是隨著Windows等多任務環境的出現,函數庫的方法過於繁瑣。如果每個程序都必須有自己的功能,以便完成諸如屏幕輸出、消息處理、內存管理對話框等操作。,那麽Windows的開發就需要允許同時運行的幾個程序共享壹組函數的單個副本,動態鏈接庫就是在這種情況下出現的。dll函數可以由系統中任何運行的應用軟件使用,而不需要重復編譯或鏈接,並且不需要將dll函數的另壹個副本加載到存儲器中。

動態鏈接庫的工作原理

動態鏈接這幾個字表明了dll是如何工作的。對於傳統的函數庫鏈接器,它復制它需要的所有庫函數,並將精確的函數地址發送給調用這些函數的程序。對於dll函數,它們存儲在壹個獨立的動態鏈接庫文件中。創建Windows程序時,鏈接過程不會將dll文件鏈接到程序,直到程序運行並調用dll中的函數。程序需要幾天時間來詢問這個函數的地址。此時,Windows在dll中查找被調用的函數,並將其地址發送給調用程序。這樣,dll達到了重用代碼的極限。

動態鏈接庫的另壹個方便之處是,對動態鏈接庫中函數的修改可以自動傳播到所有調用它的程序,而無需對程序做任何更改或處理。

dll不僅提供了函數重用的機制,還提供了數據共享的機制。任何應用程序都可以共享由加載到內存中的dll管理的內存資源塊。只包含共享數據的dll稱為資源文件,如Windows的字體文件。

Windows系統的動態鏈接庫

Windows本身支持大量的動態鏈接庫,包括Windows API函數(Krnlx Exe User Exe GDI Exe...)、各種驅動文件、Fon和Fot擴展名的字體資源文件等。Windows還為某個函數提供了特殊的dll,比如DDE編程的ddeml dll,程序安裝的ver dll。

雖然在編寫Windows程序時必然會涉及到dll,但使用Delphi的用戶大多數時候不會註意到這壹點。這是因為Delphi提供了豐富的功能,使用戶不必直接使用Windows API。另壹方面,即使使用Windows API,由於Delphi將API函數和其他Windows DLLs函數重組到幾個庫單元中,也不需要使用特殊的調用格式,所以本章的重點是編寫和調用用戶自定義dll。

用傳統的Windows編程方法創建和使用動態鏈接庫是壹件令人頭疼的事情。正如傳統的Windows編程方法本身令人望而生畏壹樣,用戶需要對定義文件工程文件進行壹系列的修改,以滿足創建和使用dll的需要。Delphi在這方面的出現,正如它在其他許多方面所做的那樣,減輕了開發人員的負擔,甚至更令人興奮。是Delphi使用dll實現了表單的重用機制。用戶可以將他們設計的表單存儲在dll中,並在需要時隨時調用它。

dll的編寫和調用

dll的編寫

在Delphi環境下寫壹個dll和寫壹個通用的應用程序沒有太大區別。其實作為DLL主體的DLL函數的編寫除了對內存資源的管理不同之外,並不需要其他特殊的手段來真正區別於工程文件。

在大多數情況下,用戶幾乎意識不到項目文件的存在,因為它通常不會顯示在屏幕上。如果要查看項目文件,可以打開“視圖”菜單並選擇項目源項。此時,項目文件的代碼將出現在屏幕的代碼編輯器中。

壹般工程文件的格式是

計劃項目標題

使用條款

程序體

dll工程文件的格式是

圖書館項目標題

使用條款

出口條款

程序體

它們之間有兩個主要區別。

壹般工程文件的文件頭使用program關鍵字,而dll工程文件的文件頭使用library關鍵字通知編譯器生成不同的可執行文件。exe文件由program關鍵字生成,DLL文件由library關鍵字生成。

如果dll要為其他應用程序輸出函數或過程,這些函數或過程必須在exports子句中列出,並且這些函數或過程本身必須用導出編譯指令進行編譯。

根據dll完成的功能,我們把dll分為以下三類。

完成壹般函數的DLLs

用於數據交換的DLLs

用於表單重用的dll

本節只討論執行壹般函數的dll,其他內容將在後面兩節討論。

編寫通用dll的步驟

編寫通用dll的步驟如下

用Delphi應用程序模板構建壹個dll程序框架。

對於Delphi用戶來說,因為沒有dll模板,所以

()建立通用應用程序,打開項目文件。

()刪除表單和相應的代碼單元。

()將工程文件中的程序改為library,刪除Uses子句中的形式,添加適當的庫單元(SysUtils類壹般需要),刪除begin…end之間的所有代碼。

用適當的文件名保存文件。此時,庫名稱後面的庫將被自動修改。

輸入程序功能代碼。如果過程函數準備好被其他應用程序調用,請在過程函數頭後面添加導出編譯指令。

建立exports子句包含供其他應用程序調用的函數和過程名。駐留的標準指示名稱索引可用於促進和加速過程/函數的調用。

輸入庫初始化代碼是可選的。

編譯器生成動態鏈接庫文件。

動態鏈接庫中的標準指示

在動態鏈接庫的輸出部分,使用了三個標準指示名稱索引駐留。

名字

Name後面跟壹個字符串常量,作為過程或函數的輸出名稱,例如

出口

InStr名稱MyInstr

其他應用程序將使用新名稱(MyInstr)調用該過程或函數。如果仍然使用原來的名稱(InStr ),當程序執行到參考點時會導致系統錯誤。

索引

Index表示分配給過程或函數的序列號。如果不使用Index,編譯器會按順序給它賦值。

Index後面的數字範圍是…使用Index加快調用過程。

居民

使用resident,加載DLL時,特定的輸出信息總是保存在內存中,這樣當其他應用程序調用此過程時,與按名稱掃描DLL條目相比,可以減少時間開銷。

例如,對於其他應用程序經常調用的那些過程或函數,使用駐留指示是合適的

出口

InStr name MyInStr resident

Lishi Xinzhi/Article/program/Delphi/201311/25207