动态链接库学习

根据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   
      Forms,   
      Unit1   
in     ' Unit1.pas '     {Form1} ;   
    
  
{$R   *.RES}    
    
  begin   
      Application.Initialize;   
      Application.CreateForm(TForm1,   Form1);   
      Application.Run;   
  end.   
    
    
  
{----------   调用者单元Unit1.PAS   ----------}    
    
  unit   Unit1;   
    
  
interface    
    
  uses   
      Windows,   Messages,   SysUtils,   Classes,   Graphics,   Controls,   Forms,   Dialogs,   
      StdCtrls,   Db,   ADODB;   
    
  type   
      TForm1   
=     class (TForm)   
          Button1:   TButton;       
{   按此按钮进行调用   }    
          ADOConnection1:   TADOConnection;                   
{   本地数据库连接,将传递给   DLL   }    
          procedure   Button1Click(Sender:   TObject);
{   调用   DLL}    
      
private    
      
public    
      end;   
    
  var   
      Form1:   TForm1;   
    
  implementation   
    
  
{$R   *.DFM}    
    
  
{   外部声明必须和   DLL中的参数列表一致,否则会运行时错误         }    
  procedure   DoTest(H:   THandle;                           
{   传递句柄               }    
                                    AConn:   TADOConnection;     
{   传递数据库连接   }    
                                    S:   
string ;                              {   传递文本信息       }    
                                    N:   Integer);                         
{   传递数值信息       }    
                                    cdecl;                                     
{   指定调用协议       }    
                                    external   
' Project2.dll ' ; {   指定过程来源       }    
    
  
{   调用过程   }    
  procedure   TForm1.Button1Click(Sender:   TObject);   
  begin   
      DoTest(Application.Handle,   
                    ADOConnection1,   
                    
' Call   OK ' ,   
                    
256 );   
  end;   
    
  end.

你可能感兴趣的:(动态链接库学习)