zoukankan      html  css  js  c++  java
  • Delphi 中的DLL 封装和调用对象技术

      

      

    Delphi用DLL来封装对象的技术主要有三种:

    用接口实现
    用纯虚和抽象类方法实现
    用类引用实现

    前两种,都是在DLL中生成类实例;第3种通过在调用方生成实例。三种方法的共同局限如下:
    调用方只能调用封装类中的virtual方法;
    调用方和提供方都必须提供类的描述,接口实现中需要提供接口描述(COM方法例外);
    不能创建DLL包含对象的派生类(接口派生除外)。

    首先,用接口实现当然包括COM实现,不过由于COM是一种实现接口技术的独立门类,所以在下面说的接口实现中不包括这方面的东西。其次用纯虚和抽象类方法实现,在《Delphi 6 Developer‘s Guide》中提及的inc文件作为公用的头文件,和刘艺在《Delphi面向对象编程思想》中提及的方法本质上是一样的。无非都是为了在调用方加入abstract关键字,而无需方法实现,从而使得编译通过。inc文件的方法是利用宏指令来达到统一处理,不用inc方法是在两处都需要进行描述。
    下面用一个例子来展示所以上面提到的集中方法。

    调用方主要文件列表为:
    UnitMain.pas  调用DLL的界面
    UnitPublic.pas  第二种方法在调用端的类描述文件
    UnitIDest.pas  接口方法和类引用方法的类描述文件
    IncDemo.inc  利用inc文件实现的类描述文件
    DLL工程主要文件列表为:
    ProDLLDemo.dpr  DLL工程文件
    UnitDLLDemo.pas  所有类实现部分的文件
    UnitIDest.pas  接口方法和类引用方法的类描述文件
    IncDemo.inc  利用inc文件实现的类描述文件
    在方法的归纳上如有遗漏,有请指教。

    UnitMain.pas 源代码:
    unit UnitMain;
    interface
    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, UnitPublic, UnitIDest;
    {$I IncDemo.inc}
    // 用于Inc方法的宏指令,如果不是用该方法可去掉上面那行
    type
      TfmMain = class(TForm)
        Memo1: TMemo;
        btnUseAbstract: TButton;
        btnUseReference: TButton;
        btnUseInterface: TButton;
        btnUseInc: TButton;
        procedure btnUseAbstractClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure btnUseInterfaceClick(Sender: TObject);
        procedure btnUseReferenceClick(Sender: TObject);
        procedure btnUseIncClick(Sender: TObject);
        private
      { Private declarations }
        public
      { Public declarations }
      end;
    var
      fmMain: TfmMain;
      function GetNewspaper: TNewspaper; external 'ProDLLDemo.dll';
      function GetCircle: ICircle; external 'ProDLLDemo.dll';
      function GetBall: TBallClass; external 'ProDLLDemo.dll';
      function GetCar: TCar; external 'ProDLLDemo.dll';

    implementation

    {$R *.dfm}

    procedure TfmMain.FormCreate(Sender: TObject);
    begin
      memo1.Lines.Clear;
    end;

    // abstract, virtual 方法示例

    procedure TfmMain.btnUseAbstractClick(Sender: TObject);
    var
      NewspaperObj: TNewspaper;
      Info: pchar;
      i: integer;
    begin
      NewspaperObj := GetNewspaper;
      if NewspaperObj = nil then
        memo1.Lines.Add('Create newspaper object failed!')
      else
      begin
        try
          GetMem(Info, 255);
          i := NewspaperObj.Read(Info);
          memo1.Lines.Add('Create newspaper object successed!');
          memo1.Lines.Add('read : ' + Info + ' return code : ' + inttostr(i));
        finally
          FreeMem(Info);
          NewspaperObj.Free;
        end;
      end;
    end;

    // interface方法示例

    procedure TfmMain.btnUseInterfaceClick(Sender: TObject);
    var
      CircleObj: ICircle;
      Info: pchar;
      i: integer;
    begin
      CircleObj := GetCircle;
      if CircleObj = nil then
        memo1.Lines.Add('Create circle object failed!')
      else
      begin
        try
          GetMem(Info, 255);
          i := CircleObj.Scroll(Info);
          memo1.Lines.Add('Create circle object successed!');
          memo1.Lines.Add('scroll : ' + Info + ' return code : ' + inttostr(i));
        finally
          FreeMem(Info);
          CircleObj := nil;
        end;
      end;
    end;

    // class reference方法示例

    procedure TfmMain.btnUseReferenceClick(Sender: TObject);
    var
      BallObj : TIBall;
      Info: pchar;
      i: integer;
    begin
      BallObj := GetBall.Create;
      if BallObj = nil then
        memo1.Lines.Add('Create ball object failed!')
      else
      begin
        try
          GetMem(Info, 255);
          i := BallObj.Play(Info);
          memo1.Lines.Add('Create ball object successed!');
          memo1.Lines.Add('play : ' + Info + ' return code : ' + inttostr(i));
        finally
          FreeMem(Info);
          BallObj.Free;
        end;
      end;
    end;

    // .inc文件方法示例

    procedure TfmMain.btnUseIncClick(Sender: TObject);
    var
      CarObj : TCar;
      Info: pchar;
      i: integer;
    begin
      CarObj := GetCar.Create;
      if CarObj = nil then
        memo1.Lines.Add('Create car object failed!')
      else
      begin
        try
          GetMem(Info, 255);
          i := CarObj.Run(Info);
          memo1.Lines.Add('Create car object successed!');
          memo1.Lines.Add('car : ' + Info + ' return code : ' + inttostr(i));
        finally
          FreeMem(Info);
          CarObj.Free;
        end;
      end;
    end;
    end.
     
    UnitPublic.pas源代码:
    unit UnitPublic;
    interface
    type
    // ----- virtual, abstract的类定义 -----
      TPaper = class(TObject);
      TNewspaper = class(TPaper)
      public
        function Read(info : pchar) : integer; virtual; abstract;
      end;
    implementation
    end.
     
    UnitIDest.pas源代码:
    unit UnitIDest;
    interface
    type
      ICircle = interface
      ['{A971701F-96EC-4201-9266-57F982805B6E}']
      function Scroll(Info : pchar) : integer;
      end;
      TIBall = class(TObject)
      public
        constructor Create; virtual; abstract;
        destructor Destroy; virtual; abstract;
        function Play(info : pchar) : integer; virtual; abstract;
      end;
      TBallClass = class of TIBall;
    implementation
    end.
     
    IncDemo.inc源文件:
    type
      TCar = class(TObject)
      public
        function Run(info: pchar): integer; virtual; {$IFNDEF INCTEST} abstract; {$ENDIF}
      end;
     
    ProDLLDemo.dpr源文件:
    library ProDLLDemo;
    uses
      SysUtils, Classes,
      UnitDLLDemo in 'UnitDLLDemo.pas',
      UnitIDest in 'UnitIDest.pas';
    {$R *.res}
    function GetNewspaper : TNewspaper;
    begin
      result := TNewspaper.Create;
    end;
    function GetCircle : ICircle;
    begin
      result := TCircle.Create;
    end;
    function GetBall : TBallClass;
    begin
      result := TBall;
    end;
    function GetCar : TCar;
    begin
      result := TCar.Create;
    end;
    exports
      GetNewspaper,
      GetCircle,
      GetBall,
      GetCar;
    end.
     
    UnitDLLDemo.pas源代码:
    unit UnitDLLDemo;
    {$DEFINE INCTEST}
    interface
    uses Sysutils, UnitIDest;
    {$I IncDemo.inc}
    { ----- 利用纯虚和抽象类实现 ----- }
    type
      TPaper = class(TObject)
      end;
      TNewspaper = class(TPaper)
      public
        constructor Create;
        destructor Destroy;
        function Read(info: pchar): integer; virtual;
      end;
    { ----- 利用接口实现 ----- }
    type
      TShape = class(TInterfacedObject)
      end;
      TCircle = class(TShape, ICircle)
      public
        constructor Create;
        destructor Destroy;
        function Scroll(info: pchar): integer;
      end;
    { ----- 利用类引用实现 ----- }
    type
      TBall = class(TIBall)
      public
        constructor Create;override;
        destructor Destroy;override;
        function Play(info : pchar) : integer; override;
      end;
    implementation
    { TNewspaper }
    constructor TNewspaper.Create;
    begin
      inherited Create;
    end;
    destructor TNewspaper.Destroy;
    begin
      inherited;
    end;
    function TNewspaper.Read(info: pchar): integer;
    var
      str: string;
    begin
      if info <> nil then
      begin
        str := self.ClassName;
        strCopy(info, PChar(str));
      end;
      result := 1;
    end;
    { TCircle }
    constructor TCircle.Create;
    begin
      inherited Create;
    end;
    destructor TCircle.Destroy;
    begin
      inherited;
    end;
    function TCircle.Scroll(info: pchar): integer;
    var
      str: string;
    begin
      if info <> nil then
    begin
        str := self.ClassName;
        strCopy(info, PChar(str));
      end;
      result := 2;
    end;
    { TBall }
    constructor TBall.Create;
    begin
      // inherited Create;
    end;
    destructor TBall.Destroy;
    begin
      // inherited;
    end;
    function TBall.Play(info: pchar): integer;
    var
      str: string;
    begin
      if info <> nil then
      begin
        str := self.ClassName;
        strCopy(info, PChar(str));
      end;
      result := 3;
    end;
    { ----- 利用Inc文件实现 ----- }
    function TCar.Run(info: pchar): integer;
    var
      str: string;
    begin
      if info <> nil then
      begin
        str := self.ClassName;
        strCopy(info, PChar(str));
      end;
      result := 4;
    end;
    end.
     
    [参考文献]:
    1. Delphi面向对象编程思想,第8章,刘艺, 2003.9, 机械工业出版社.
    2. Delphi 6 Developer‘s Guide, p209, Steve Teixeira, SAMS, 2001.



  • 相关阅读:
    zigbee芯片
    笔记本ubuntu安装wifi驱动(未完成)
    我错了的N个学习
    《华为工作法》读书笔记
    bbblack的网络socket通信实验
    NB-IOT连接移动onenet平台流程
    移动onenet基础通信套件V1.08版本的AT指令测试
    CC3200使用MQTT的SSL加密证书可用日期修改
    利尔达NB-IOT模块烧写固件的步骤
    树莓派相机
  • 原文地址:https://www.cnblogs.com/ntearn/p/2474479.html
Copyright © 2011-2022 走看看