天天看點

在Delphi中調用DLL

<一>在Delphi中靜态調用DLL top

調用一個DLL比寫一個DLL要容易一些。首先給大家介紹的是靜态調用方法,稍後将介紹動态調用方法,并就兩種方法做一個比較。同樣的,我

們先舉一個靜态調用的例子。

unit Unit1;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Edit1: TEdit;

Button1: TButton;

procedure Button1Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

//本行以下代碼為我們真正動手寫的代碼

function TestDll(i:integer):integer;stdcall;

external ’Delphi.dll’;

procedure TForm1.Button1Click(Sender: TObject);

begin

Edit1.Text:=IntToStr(TestDll(1));

end;

end.

上面的例子中我們在窗體上放置了一個編輯框(Edit)和一個按鈕(Button),并且書寫了很少的代碼來測試我們剛剛編寫的Delphi.dll。大

家可以看到我們唯一做的工作是将TestDll函數的說明部分放在了implementation中,并且用external語句指定了Delphi.dll的位置。(本例中

調用程式和Delphi.dll在同一個目錄中。)讓人興奮的是,我們自己編寫的TestDll函數很快被Delphi認出來了。您可做這樣一個實驗:輸入“

TestDll(”,很快Delphi就會用fly-by提示條提示您應該輸入的參數是什麼,就像我們使用Delphi中定義的其他函數一樣簡單。注意事項有以

下一些:

一、調用參數用stdcall。

和前面提到的一樣,當引用DLL中的函數和過程時也要使用stdcall參數,原因和前面提到的一樣。

二、用external語句指定被調用的DLL檔案的路徑和名稱。

正如大家看到的,我們在external語句中指定了所要調用的DLL檔案的名稱。沒有寫路徑是因為該DLL檔案和調用它的主程式在同一目錄下。如

果該DLL檔案在C:/,則我們可将上面的引用語句寫為external ’C:/Delphi.dll’。注意檔案的字尾.dll必須寫上。

三、不能從DLL中調用全局變量。

如果我們在DLL中聲明了某種全局變量,如:var s:byte 。這樣在DLL中s這個全局變量是可以正常使用的,但s不能被調用程式使用,既s不能

作為全局變量傳遞給調用程式。不過在調用程式中聲明的變量可以作為參數傳遞給DLL。

四、被調用的DLL必須存在。

這一點很重要,使用靜态調用方法時要求所調用的DLL檔案以及要調用的函數或過程等等必須存在。如果不存在或指定的路徑和檔案名不正确的

話,運作主程式時系統會提示“啟動程式時出錯”或“找不到*.dll檔案”等運作錯誤。

<二>在Delphi中動态調用DLL top

動态調用DLL相對複雜很多,但非常靈活。為了全面的說明該問題,這次我們舉一個調用由C++編寫的DLL的例子。首先在C++中編譯下面的DLL源

程式。

#include

extern ”C” _declspec(dllexport)

int WINAPI TestC(int i)

{

return i;

}

編譯後生成一個DLL檔案,在這裡我們稱該檔案為Cpp.dll,該DLL中隻有一個傳回整數類型的函數TestC。為了友善說明,我們仍然引用上面的

調用程式,隻是将原來的Button1Click過程中的語句用下面的代碼替換掉了。

procedure TForm1.Button1Click(Sender: TObject);

type

TIntFunc=function(i:integer):integer;stdcall;

var

Th:Thandle;

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)); {調用TestC函數}

end

else

ShowMessage(’TestC函數沒有找到’);

finally

FreeLibrary(Th); {釋放DLL}

end

else

ShowMessage(’Cpp.dll沒有找到’);

end;

大家已經看到了,這種動态調用技術很複雜,但隻要修改參數,如修改LoadLibrary(’Cpp.dll’)中的DLL名稱為’Delphi.dll’就可動态更改

所調用的DLL。

一、定義所要調用的函數或過程的類型。

在上面的代碼中我們定義了一個TIntFunc類型,這是對應我們将要調用的函數TestC的。在其他調用情況下也要做同樣的定義工作。并且也要加

上stdcall調用參數。

二、釋放所調用的DLL。

我們用LoadLibrary動态的調用了一個DLL,但要記住必須在使用完後手動地用FreeLibrary将該DLL釋放掉,否則該DLL将一直占用記憶體直到您退

出Windows或關機為止。

現在我們來評價一下兩種調用DLL的方法的優缺點。靜态方法實作簡單,易于掌握并且一般來說稍微快一點,也更加安全可靠一些;但是靜态方

法不能靈活地在運作時裝卸所需的DLL,而是在主程式開始運作時就裝載指定的DLL直到程式結束時才釋放該DLL,另外隻有基于編譯器和連結器

的系統(如Delphi)才可以使用該方法。動态方法較好地解決了靜态方法中存在的不足,可以友善地通路DLL中的函數和過程,甚至一些老版本

DLL中新添加的函數或過程;但動态方法難以完全掌握,使用時因為不同的函數或過程要定義很多很複雜的類型和調用方法。對于初學者,筆者

建議您使用靜态方法,待熟練後再使用動态調用方法。

繼續閱讀