delphi 編寫dll文件

dll文件簡介:

它是Dynamic Link Library 的縮寫形式,DLL 是一個包含可由多個程序同時使用的代碼和數據的庫,DLL不是可執行文件。動態鏈接提供了一種方法,使進程可以調用不屬於其可執行代碼的函數。函數的可執行代碼位於一個 DLL 中,該 DLL 包含一個或多個已被編譯、鏈接並與使用它們的進程分開存儲的函數。DLL 還有助於共享數據和資源。多個應用程序可同時訪問內存中單個DLL 副本的內容。DLL 是一個包含可由多個程序同時使用的代碼和數據的庫。例如,在 Windows 操作系統中,Comdlg32 DLL 執行與對話框有關的常見函數。因此,每個程序都可以使用該 DLL 中包含的功能來實現“打開”對話框。這有助於促進代碼重用和內存的有效使用。

  通過使用 DLL,程序可以實現模塊化,由相對獨立的組件組成。例如,一個計帳程序可以按模塊來銷售。可以在運行時將各個模塊加載到主程序中(如果安裝了相應模塊)。因爲模塊是彼此獨立的,所以程序的加載速度更快,而且模塊只在相應的功能被請求時才加載。

  此外,可以更爲容易地將更新應用於各個模塊,而不會影響該程序的其他部分。例如,您可能具有一個工資計算程序,而稅率每年都會更改。當這些更改被隔離到 DLL 中以後,您無需重新生成或安裝整個程序就可以應用更新

 

編寫DLL的目的是爲了輸出例程供其他程序調用,因此在DLL的工程文件中要把輸出的例程用Exports關鍵字引出。在調用DLL的應用程序中,需要聲明用到的DLL中的方法,聲明格式要和DLL中的聲明一樣。訪問DLL中的例程有靜態調用和動態調用兩種方式。靜態調用方式就是在單元的Interface部分用External指示字列出要從DLL中引入的例程;動態調用方式就是通過調用Windows的API包括LoadLibrary函數、GetProcAddress函數以及FreeLibrary函數動態的引入DLL中的例程。
  靜態調用方式所需的代碼較動態調用方式所需的少,但存在着一些不足,一是如果要加載的DLL不存在或者DLL中沒有要引入的例程,這時候程序就自動終止運行;二是DLL一旦加載就一直駐留在應用程序的地址空間,即使DLL已不再需要了。動態調用方式就可解決以上問題,它在需要用到DLL的時候才通過LoadLibrary函數引入,用完後通過FreeLibrary函數從內存中卸載,而且通過調GetProcAddress函數可以指定不同的例程。最重要的是,如果指定的DLL出錯,至多是API調用失敗,不會導致程序終止。以下將通過具體的實例說明說明這調用方式的使用方法。
  1.靜態調用方式
  示例程序創建了一個DLL,其中僅包含一個求兩個整數的和的函數,在主程序中輸入兩個整數,通過調用該DLL,即可求出兩個整數的和,如圖1所示。
 
     圖1 DLL的靜態調用  
  該DLL的程序代碼如下:
library AddNum;
uses
SysUtils,
Classes;
{$R *.res}
function AddNumber(Num1,Num2:integer):integer;stdcall; //定義求和函數
 begin
  result:=Num1+Num2;
 end;
  exports
  AddNumber; //引出求和函數
 begin
end. 
  主程序在調用該DLL時,首先在interface部分聲明要調用的函數:
function AddNum(Num1,Num2:integer):integer;stdcall;external 'AddNum.dll'
name 'AddNumber';  
  然後在按鈕控件的事件中寫入如下代碼:
procedure TForm1.Button1Click(Sender: TObject);
var
 Number1,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所示。
 
     圖2 DLL的動態調用  
  程序中定義了一個ShowCalendar函數,返回在這個窗體中設定的日期。函數定義如下:
function ShowCalendar(AHandle: THandle; ACaption: String): TDateTime;
var
 DLLForm: TDLLForm;
begin
 Application.Handle := AHandle;
 DLLForm := TDLLForm.Create(Application); //創建並顯示窗體
 try
  DLLForm.Caption := ACaption;
  DLLForm.ShowModal; //顯示方式爲模式化
  Result := DLLForm.calDLLCalendar.CalendarDate; //返回設定日期
 finally
  DLLForm.Free; //用完後卸載該窗體
 end;
end; 
  在DLL的工程文件中用exports ShowCalendar; 語句引出該函數。下面通過一個簡單的應用程序測試一下該DLL文件。新建一個工程文件,在窗體中放置一個Label控件和一個按鈕控件,在按鈕控件的OnClick事件中編寫如下代碼:
procedure TMainForm.Button1Click(Sender: TObject);
var
 OneHandle : THandle; //定義一個句柄變量
begin
 OneHandle := LoadLibrary('Clendar.dll'); //動態載入DLL,並返回其句柄
 try
  if OneHandle <> 0 then //如果載入成功則獲取ShowCalendar函數的地址
   @ShowCalendar := GetProcAddress(OneHandle, 'ShowCalendar');
   if not (@ShowCalendar = nil) then
    //如果找到該函數則在主窗體的Label1中顯示DLL窗體中設定的日期
    Label1.Caption := DateToStr(ShowCalendar(Application.Handle, Caption))
   else
    RaiseLastWin32Error;
 finally
  FreeLibrary(OneHandle); //調用完畢收回DLL佔用的資源
 end;
end; 
  從以上程序中可以看到DLL的動態調用方式比靜態調用方式的優越之處。DLL例程在用到時才被調入,用完後就被卸載,大大減少了系統資源的佔用。在調用LoadLibrary函數時可以明確指定DLL的完整路徑,如果沒有指定路徑,運行時首先查找應用程序載入的目錄,然後是Windows系統的System目錄和環境變量Path設定的路徑

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章