創建DLL動態連接庫

創建DLL動態連接庫
     Windows 的執行文件可以劃分爲兩種形式程序和動態連接庫(DLLs)。一般程序運行是用.EXE文件,但應用程序有時也可以調用存儲在DLL 中的函數。
     當我們調用Windows 中的API 函數的時候,實際上就是調用存儲在DLL 中的函數。
     在如下幾種情況下,調用DLL 是合理的:
     1) 不同的程序使用相同的DLL ,這樣只需要將DLL 在內存中裝載一次,節省了內存的開銷。
     2) 當某些內容需要升級的時候,如果使用DLL 只需要改變DLL 就可以了,而不需要把整個程序都進行變動。
     3) 由於DLL 是獨立於語言的,所以,當不同語言習慣的人共同開發一個大型項目的時候,使用DLL 便於程序系統的交流,當然,Delphi開發的DLL 也可以在諸如Visual BASIC,C++ 等系
統中使用。
     下面通過幾個例子,說明Delphi開發動態連接庫的方法和規範。    
     第一節 動態連接庫的構建和調用方法
     一、動態連接庫構建
     File---New---Other---DLL Wizard
     這就創建了一個動態連接庫的基本模塊
     library Project2;
     uses
       SysUtils,
       Classes;
    {$R *.res}
     begin
     end.
     把工程名改爲Mydll,並寫入必要的函數
     library mydll;
     uses
       SysUtils,Classes,Dialogs,windows;
     function Triple(N:Integer):integer;stdcall;
     begin
       result:=N+3;
     end;
     function Double(N:Integer):integer;stdcall;
     begin
       result:=N+2;
     end;
     function Triple1(N:Integer):integer;stdcall;
     begin
       showmessage('計算N+3');
       result:=N+3;
     end;
     function Double1(N:Integer):integer;stdcall;
     begin
       messagebox(0,'計算N+2','計算N+2',mb_ok);
       result:=N+2;
     end;
    exports
      Triple name 'Tr',
      Double name 'Do',
      Triple1 name 'TrM',
      Double1 name 'DoM';
     Triple,Double,Triple1,Double1;
   {$R *.RES}
   begin
   end.
     其中函數:Triple:把傳入值加三
               Double:把傳入值加二
               Triple1:把傳入值加三並顯示提示
               Double1:把傳入值加二並顯示提示
     從這個例子中可以看出DLL 程序的幾個規則:
     1) 在DLL 程序中,輸出函數必須被聲明爲stdcall,以使用標準的Win32 參數傳遞技術來代替優化的Register。
     (說明:在Delphi中Register方式是缺省的調用約定,這個約定儘量採用寄存器來傳遞參數,傳遞次序從左到右,最多可用到3個CPU 的寄存器,如果參數多於3 個,剩下的就通過棧來傳送,使用寄存器傳送可保證參數傳遞的速度最快。
     而stdcall 方式是通過Windows 的標準調用來傳遞參數,傳遞秩序從左到右,這種方式適合調用Windows 的API ,在DLL 中,當然要使用這種方式)。
     2)所有的輸出函數都必須列在exports子句下面,這使的子例程在DLL外部就可以看到。
    exports
      Triple name 'Tr',
      Double name 'Do',
      Triple1 name 'TrM',
      Double1 name 'DoM';
   
     列出了用戶使用這個函數的接口名字。雖然別名不是必須的,但最好給個別名,以便用戶程序更容易找到這個函數,同時還要指出,Delphi 6.0取消了Delphi 5.0中允許使用的index ,如果還用Index來指明接口名字,Delphi 6.0中將提示錯誤。
     實例中給出了兩種提示方法,主要想說明一個問題:
     showmessage(''),是VCL 提供的函數,由於多次編譯VCL,做出的程序會比較大。
     而messagebox(0,'','',mb_ok)   是Windows提供的API 函數,做出的程序會比較小。
     這就是說,編寫DLL 程序的時候,要儘量避免多次編譯VCL 。作爲一個實例,這裏把兩種方法都列出來了。
     保存
     編譯:Projrct---Build Mydll
     這就完成了一個簡單的動態連接庫的編寫。
     二、動態連接庫的調用
     首先在implementation下做調用聲明
const
   gdi32='mydll.dll';
function triple(n:integer):integer;stdcall;external gdi32 name 'Tr';
function Double(N:Integer):integer;stdcall;external gdi32 name 'Do';
function triple1(n:integer):integer;stdcall;external gdi32 name 'TrM';
function Double1(N:Integer):integer;stdcall;external gdi32 name 'DoM';
     以後程序中就可以作爲普通的函數使用了,例如:
procedure TForm1.Button1Click(Sender: TObject);
var N:integer;
begin
   N:=updown1.position;
   edit1.text:=inttostr(triple(N));
end;
     第二節 DLL 中的Delphi窗體
     一、在DLL 中放置窗的的方法
     在DLL 中,除了放置標準的函數和過程以外,也可以放置已經做好的的delphi窗體,也可以把做好的窗體供其它程序使用,方法是:
    1)首先按普通方法制作窗體,不過在interface區域,對接口函數做如下聲明
    function Createform(capt:string):string;stdcall;
  
    2)在implementation下加入接口函數
function Createform(capt:string):string;stdcall;
var   Form1: TForm1;
begin
   form1:=Tform1.Create(application);
   form1.show;
   form1.caption:=capt;
end;

   3)製作DLL 動態連接庫,但要聲明:
uses
   unit1 in 'unit1.pas';
exports
{寫入接口標示符}
Createform name 'Myform';
   4)調用窗體的程序按普通方法制作,但是 在implementation下首先聲明要調用的DLL函數
const
   gdi32='myFormdll.dll';
   function Createform(capt:string):string;stdcall;external gdi32 name 'Myform';

procedure TForm3.Button1Click(Sender: TObject);
var n,m:string;
begin
   m:='我的窗體';
   Createform(m);
end;
     二、DLL 中的調用窗體時的數據傳遞
     在窗體調用時,可以用普通的函數方法傳遞數據,下面舉個例子。
     1)建立窗體
     做一個改變顏色窗體,放在DLL 中,可以用普通的方法來做,但要作如下聲明:
     function mycolor(col:longint):longint;stdcall;
     function Getcolor:longint;stdcall;
     其中,mycolor爲構造窗體;Getcolor爲傳遞顏色數據。
     在implementation區聲明一個窗體內全局的變量
     var color1:longint;
     下面寫出相應的程序
function mycolor(col:longint):longint;stdcall;
var   Form1: TForm1;
begin
   form1:=Tform1.Create(application);
   form1.show;
   form1.panel1.Color:=col;
   form1.edit1.Text:=inttostr(form1.panel1.Color);
   result:=color1;
end;

function Getcolor:longint;stdcall;
begin
   result:=color1;
end;

procedure TForm1.ScrollBar1Change(Sender: TObject);
begin
   panel2.Color:=RGB(ScrollBar1.Position,ScrollBar2.Position,ScrollBar3.Position);
   edit2.Text:=inttostr(panel2.Color);
   color1:=panel2.Color;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
    Free;   //析構Form1
end;
     2)建立動態連接庫
     運行成功後,再建立動態連接庫:
library FormDLL;
{從文件調入}
uses
   unit1 in 'unit1.pas';
exports
{寫入接口標示符}
Mycolor name 'My',
Getcolor name 'Get';
begin
end.
     3)建立調用的程序
     首先聲明要調用的DLL函數
const
   gdi32='formDll.dll';
   function Mycolor(col:longint):longint;stdcall;external gdi32 name 'My';
   function Getcolor:longint;stdcall;external gdi32 name 'Get';
     然後寫出相應的程序
procedure TForm1.Button1Click(Sender: TObject);
begin
   Mycolor(color);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
    color:=getcolor;
end;
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章