关于Delphi中DLL封装对象的几种方法整理及体会

 
关于Delphi中DLL封装对象的几种方法整理及体会

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

  1. 用接口实现
  2. 用纯虚和抽象类方法实现
  3. 用类引用实现
前两种,都是在DLL中生成类实例;第3种通过在调用方生成实例。三种方法的共同局限如下:
  • 调用方只能调用封装类中的virtual方法;
  • 调用方和提供方都必须提供类的描述,接口实现中需要提供接口描述(COM方法例外);
  • 不能创建DLL包含对象的派生类(接口派生除外)。
首先,用接口实现当然包括COM实现,不过由于COM是一种实现接口技术的独立门类,所以在下面说的接口实现中不包括这方面的东西。其次用纯虚和抽象类方法实现,在《Delphi 6 Developer‘s Guide》中提及的inc文件作为公用的头文件,和刘艺在《Delphi面向对象编程思想》中提及的方法本质上是一样的。无非都是为了在调用方加入abstract关键字,而无需方法实现,从而使得编译通过。inc文件的方法是利用宏指令来达到统一处理,不用inc方法是在两处都需要进行描述。

 

下面用一个例子来展示所以上面提到的集中方法。
调用方主要文件列表为:

  1. UnitMain.pas  调用DLL的界面
  2. UnitPublic.pas  第二种方法在调用端的类描述文件
  3. UnitIDest.pas  接口方法和类引用方法的类描述文件
  4. IncDemo.inc  利用inc文件实现的类描述文件

DLL工程主要文件列表为:
  1. ProDLLDemo.dpr  DLL工程文件
  2. UnitDLLDemo.pas  所有类实现部分的文件
  3. UnitIDest.pas  接口方法和类引用方法的类描述文件
  4. 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.

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值