Delphi 動態與靜態呼叫DLL

2021-07-09 17:43:12 字數 3740 閱讀 5266

摘要:本文闡述了 windows  環境下動態鏈結庫的概念和特點,對靜態呼叫和動態呼叫兩種呼叫方式作出了比較,並給出了 delphi  中應用動態鏈結庫的例項。 

一、動態鏈結庫的概念

動態鏈結庫( dynamic link library  ,縮寫為 dll  )是乙個可以被其它應用程式共享的程式模組,其中封裝了一些可以被共享的例程和資源。動態鏈結庫檔案的副檔名一般是 dll  ,   也有可能是 drv  、 sys  和 fon  ,它和可執行檔案( exe  )非常類似,區別在於 dll  中雖然包含了可執行**卻不能單獨執行,而應由 windows  應用   程式直接或間接呼叫。 

動態鏈結是相對於靜態鏈結而言的。所謂靜態鏈結是指把要呼叫的函式或者過程鏈結到可執行檔案中,成為可執行檔案  的一部分。換句話說,函式和過程的**就在程式的 exe  檔案中,該檔案包含了執行時所需的全部**。當多個程式都呼叫相同函式時,記憶體中就會存在這個函式  的多個拷貝,這樣就浪費了寶貴的記憶體資源。而動態鏈結所呼叫的函式**並沒有被拷貝到應用程式的可執行檔案中去,而是僅僅在其中加入了所呼叫函式的描述信  息(往往是一些重定位資訊)。僅當應用程式被裝入記憶體開始執行時,在 windows  的管理下,才在應用程式與相應的 dll  之間建立鏈結關係。當要執行所調  用 dll  中的函式時,根據鏈結產生的重定位資訊, windows  才轉去執行 dll  中相應的函式**。 

一般情況下,如果乙個應用程式使  用了動態鏈結庫, win32  系統保證記憶體中只有 dll  的乙份複製品,這是通過記憶體對映檔案實現的。 dll  首先被調入 win32  系統的全域性堆疊,然後對映到  呼叫這個 dll  的程序位址空間。在 win32  系統中,每個程序擁有自己的 32  位線性位址空間,如果乙個 dll  被多個程序呼叫,每個程序都會收到該 dll  的   乙份映像。與 16  位 windows  不同,在 win32  中 dll  可以看作是每個程序自己的**。 

二、動態鏈結庫的優點

1  .   共享**、資源和資料 

使用 dll  的主要目的就是為了共享**, dll  的**可以被所有的 windows  應用程式共享。 

2  .   隱藏實現的細節 

dll  中的例程可以被應用程式訪問,而應用程式並不知道這些例程的細節。 

3  .   拓展開發工具如 delphi  的功能 

由於 dll  是與語言無關的,因此可以建立乙個 dll  ,被 c++  、 vb  或任何支援動態鏈結庫的語言呼叫。這樣如果一種語言存在不足,就可以通過訪問另一種語言建立的 dll  來彌補。 

三、動態鏈結庫的實現方法

1  . load-time dynamic linking 

這種用法的前提是在編譯之前已經明確知道要呼叫 dll  中的哪幾個函式,編譯時在目標檔案中只保留必要的鏈結資訊,而不含 dll  函式的**;當程式執行時,利用鏈結資訊載入 dll  函式**並在記憶體中將其鏈結入呼叫程式的執行空間中,其主要目的是便於**共享。 

2  . run-time dynamic linking  

這種方式是指在編譯之前並不知道將會呼叫哪些 dll  函式,完全是在執行過程中根據需要決定應呼叫哪個函式,並用 loadlibrary  和 getprocaddress  動態獲得 dll  函式的入口位址。  

四、dll 的兩種呼叫方式在delphi 中的比較

編寫dll 的目的是為了輸出例程供其他程式呼叫,因此在dll 的工程檔案中要把輸出的例程用exports 關鍵字引出。在呼叫dll 的應用程式中,需要 宣告用到的dll 中的方法,宣告格式要和dll 中的宣告一樣。訪問dll 中的例程有靜態呼叫和動態呼叫兩種方式。靜態呼叫方式就是在單元的 inte***ce 部分用external 指示字列出要從dll 中引入的例程;動態呼叫方式就是通過呼叫windows 的api 包括 loadlibrary 函式、getprocaddress 函式以及freelibrary 函式動態的引入dll 中的例程。

靜態呼叫 方式所需的**較動態呼叫方式所需的少,但存在著一些不足,一是如果要載入的dll 不存在或者dll 中沒有要引入的例程,這時候程式就自動終止執行;二是 dll 一旦載入就一直駐留在應用程式的位址空間,即使dll 已不再需要了。動態呼叫方式就可解決以上問題,它在需要用到dll 的時候才通過 loadlibrary 函式引入,用完後通過freelibrary 函式從記憶體中解除安裝,而且通過調getprocaddress 函式可以指定不同的例程。 最重要的是,如果指定的dll 出錯,至多是api 呼叫失敗,不會導致程式終止。以下將通過具體的例項說明說明這呼叫方式的使用方法。

1 . 靜態呼叫方式

示例程式建立了乙個dll ,其中僅包含乙個求兩個整數的和的函式,在主程式中輸入兩個整數,通過呼叫該dll ,即可求出兩個整數的和,如圖1 所示。 

該dll 的程式**如下: 

library addnum;

uses

sysutils,

classes;

function addnumber(num1,num2:integer):integer;stdcall; // 定義求和函式

begin

result:=num1+num2;

end;

exports

addnumber; // 引出求和函式

begin

end. 

主程式在呼叫該dll 時,首先在inte***ce 部分宣告要呼叫的函式: 

function  addnum(num1,num2:integer):integer;stdcall;external 'addnum.dll'

name 'addnumber'; 

然後在按鈕控制項的事件中寫入如下**: 

procedure tform1.button1click(sender: tobject);

varnumber1,number2:integer;

sum:integer;

begin

number1:=strtoint(edit1.text);

number2:=strtoint(edit2.text);

sum:=addnum(number1,number2); // 呼叫求和函式計算結果

edit3.text:=inttostr(sum);

end; 

2 .動態呼叫方式

這個示例程式建立了乙個顯示日期的dll ,其中包含乙個窗體,如圖2 所示。 

程式中定義了乙個showcalendar 函式,返回在這個窗體中設定的日期。函式定義如下: 

在dll 的工程檔案中用exports showcalendar;  語句引出該函式。下面通過乙個簡單的應用程式測試一下該dll 檔案。新建乙個工程檔案,在窗體中放置乙個label 控制項和乙個按鈕控制項,在按鈕控制項的onclick 事件中編寫如下**: 

從以上程式中可以看到dll 的動態呼叫方式比靜態呼叫方式的優越之處。dll 例程在用到時才被調入,用完後就被解除安裝,大大減少了系統資源的占用。在呼叫 loadlibrary 函式時可以明確指定dll 的完整路徑,如果沒有指定路徑,執行時首先查詢應用程式載入的目錄,然後是windows 系統的 system 目錄和環境變數path 設定的路徑。

五、結束語

由於動態鏈結庫可以實現**和資源的共享,大大減少系統資源的占用,因此在當今的應用程式開發中起著非常重要的作用。delphi 是現今流行的應用軟體開發工具,本文就如何在delphi 中使用動態鏈結庫給出了一定程度上的闡述。

php 靜態呼叫與動態呼叫

當用 使用方法是被認為該方法為靜態方法,靜態方法中不允許使用 this,因為靜態方法的呼叫不需要例項化,而 this是例項化後才出現的,所以靜態方法類似於乙個普通的函式 靜態方法是加栽到記憶體.而且還少了 new 的記憶體空間.速度相對快一點效率好點tukiz29 例 class a else cl...

DELPHI中動態呼叫dll

顯式例子 unit main inte ce uses windows,messages,sysutils,variants,classes,graphics,controls,forms,dialogs,stdctrls,extctrls,grids,dbgrids,db,dbtables,dbc...

delphi動態呼叫dll窗體

宣告 tshowform function ahandle thandle acaption pchar boolean stdcall 呼叫 procedure tform1.n5click sender tobject var mainfrm,dllform thandle showform t...