根據Delphi提供的有關 DLL編寫和調用的幫助信息,你可以很快完成一般的 DLL編寫和調用的 應用程序。本文介紹的主題是如何編寫和調用能夠傳遞各種參數(包括對象實例)的 DLL。例如, 主叫程序傳遞給 DLL一個ADOConnection 對象示例作為參數, DLL中的函數和過程調用通過該對象 實例訪問數據庫。
需要明確一些基本概念。對於 DLL,需要在主程序中包含 exports子句,用於向外界提供調用 接口,子句中就是一系列函數或過程的名字。對於主叫方(調用 DLL的應用程序或其它的 DLL), 則需要在調用之前進行外部聲明,即external保留字指示的聲明。這些是編寫 DLL和調用 DLL必須 具備的要素。
另外需要了解Object Pascal 中有關調用協議的內容。在Object Pascal 中,對於過程和函數 有以下五種調用協議:
指示字 參數傳遞順序 參數清除者 參數是否使用寄存器
register 自左向右 被調例程 是
pascal 自左向右 被調例程 否
cdecl 自右向左 調用者 否
stdcall 自右向左 被調例程 否
safecall 自右向左 被調例程 否
這裡的指示字就是在聲明函數或過程時附加在例程標題之後的保留字,默認為register,即是 唯一使用 CPU寄存器的參數傳遞方式,也是傳遞速度最快的方式;
pascal: 調用協議僅用於向後兼容,即向舊的版本兼容;
cdecl: 多用於 C和 C++語言編寫的例程,也用於需要由調用者清除參數的例程;
stdcall: 和safecall主要用於調用Windows API 函數;其中safecall還用於雙重接口。
在本例中,將使用調用協議cdecl ,因為被調用的 DLL中,使用的數據庫連接是由主叫方傳遞 得到的,並且需要由主叫方處理連接的關閉和銷毀。
下面是 DLL完整源程序和主叫程序完整源程序。包括以下四個文件:
Project1.DPR {主叫程序}
Unit1.PAS {主叫程序單元}
Project2.DPR {DLL}
Unit2.PAS {DLL單元}
{---------- DLL 主程序 Project2.DPR ----------}
library Project2;
uses
SysUtils,
Classes,
Unit2 in ‘Unit2.pas‘ {Form1};
{$R *.RES}
{ 下面的語句用於向調用該 DLL的程序提供調用接口 }
exports
DoTest; { 過程來自單元Unit2 }
begin
end.
{---------- DLL中的單元 Unit2.PAS ----------}
unit Unit2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Db, ADODB, StdCtrls, Menus;
type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;{ 本地數據庫連接 }
Memo1: TMemo; { 用於顯示信息 }
private
public
end;
{ 該過程向外提供 }
procedure DoTest(H: THandle; { 獲得調用者的句柄 }
AConn: TADOConnection;{ 獲得調用者的數據庫連接 }
S: string; { 獲得一些文本信息 }
N: Integer); { 獲得一些數值信息 }
cdecl; { 指定調用協議 }
implementation
{$R *.DFM}
procedure DoTest(H: THandle; AConn: TADOConnection; S: string; N: Integer);
begin
Application.Handle := H; { 將過程的句柄賦值為調用者的句柄 }
{ 上面語句的作用在於, DLL的句柄和調用者的句柄相同,在任務欄中就不會 }
{ 各自出現一個任務標題了。 }
with TForm1.Create(Application) do try{ 創建窗體 }
Memo1.Lines.Append(‘成功調用‘); { 顯示一行信息 }
ADOConnection1 := AConn; { 獲得數據庫連接的實例 }
Memo1.Lines.Append(
ADOConnection1.ConnectionString +
‘ - ‘ + S + ‘ - ‘ + IntToStr(N)); { 根據得到的參數顯示另一行信息 }
ShowModal; { 模式化顯示窗體 }
finally
Free; { 調用結束時銷毀窗口 }
end;
end;
end.
{---------- 調用者 Project1.DPR,很普通的工程文件 ----------}
program Project1;
uses