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.

转载于:https://www.cnblogs.com/ntearn/archive/2012/04/28/2474479.html

Delphi 中的DLL 封装和调用对象技术相关推荐

  1. 多个类的DLL封装及调用

    网上大多是将函数封装成dll的教程,类的封装也是基本相似的. 创建DLL 在VS2010中新建一个win32->dll工程.如我建立的工程名为FaceDLL 添加facedll.h的头文件(里面 ...

  2. C/C++ DLL封装及调用

    目录 操作步骤 1. 创建dll 2. 创建测试程序 需求:C开发的控制台程序封装为dll,用于C++程序调用 开发环境:VS 2013 Pro 操作步骤 1. 创建dll 新建工程:C/C++ -& ...

  3. Delphi中的dll操作

    利用delphi dll wizard进行dll的编写.创建:保存时改dll名称library test2;usesSysUtils,Classes,forms,dialogs;{$R *.res} ...

  4. Delphi中一些DLL的运用。

    临时转载一些别人的代码: dll 调用部分:{****************************************************************} { } { Proje ...

  5. delphi 中的dll编程注意事项

    虽然delphi不区分大小写,但若编写DLL就应当注意了,它是区分大小写的.导出函数,与封装类皆是如此.一定要注意.

  6. 在Delphi中调用外部DLL 之External DLL 导入DLL

    调用一个DLL比写一个DLL要容易一些.首先给大家介绍的是静态调用方法,稍后将介绍动态调用方法,并就两种方法做一个比较.同样的,我们先举一个静态调用的例子. unit Unit1;interfaceu ...

  7. delphi dll创建及调用

    第一章 DLL简单介绍 由于在目前的学习工作中,需要用到DLL文件,就学习了下,在这里作个总结. 首先装简单介绍下DLL: 1,减小可执行文件的大小 DLL技术的产生有很大一部分原因是为了减小可执行文 ...

  8. (转)剖析Delphi中的构造和析构

    剖析Delphi中的构造和析构 1 Delphi中的对象模型: 2 1.1 对象名表示什么? 2 1.2 对象存储在哪里? 2 1.3 对象中存储了什么?它们是如何存储的? 3 2 构造函数与创建对象 ...

  9. Delphi中判断控件的详细类型

    var   t:TFrmMain; begin   if(self is TForm) then   begin     if(self.ClassType=tform) then     begin ...

  10. C/C++: C++可调用对象详解

    C++中有几种可调用对象:函数,函数指针,lambda表达式,bind创建的对象,以及重载了函数调用符的类. 1. 函数 函数偏基础的东西,在这里不再叙述.重点讲下C++11的某些重要特性和函数指针. ...

最新文章

  1. 《OpenCV3编程入门》学习笔记10 角点检测(二)Shi-Tomasi角点检测
  2. 赛迪展望 | 一文了解“2021年中国先进计算产业发展趋势”
  3. iOS进程间通信之CFMessagePort
  4. linux mysql 二进制包_mysql5.7 二进制包安装
  5. 【STM32】硬件随机数程序示例
  6. python上一行的代码打错了怎么办_写Python代码过程中碰到各种错误异常要怎么样去处理?...
  7. ITU-T Technical Paper: QoS 的参数(非常的全,共计88个)
  8. 基于java的药品库房管理系统
  9. 使用CSS实现国际象棋棋盘
  10. 档案盒正面标签制作_使用WORD制作档案盒侧面标签方法
  11. 用户自动设置报表格式
  12. 网页自动弹出js——你懂的
  13. 配置Stratified-Transformer、Point-Transformer系列
  14. opencv+python+OpenPose姿态实时识别
  15. 关于项目上线(新浪云)
  16. 公司接口裸奔10年了,有必要用API接口签名验证吗?
  17. MSTAR数据库结合深度学习(SAR图像目标检测与识别)
  18. 20-40-60法则
  19. Python一键保存千张表情包图
  20. if 下与 或执行与否

热门文章

  1. Kubernetes 小白学习笔记(11)--搭建一个kubernetes集群-为worker节点配置命令行交互环境
  2. 微信小程序this.setData如何修改对象、数组中的值
  3. html怎么设背景颜色加上文字,怎么给视频添加文字 视频底部加文字,设置文字背景颜色、文字显示时间...
  4. oracle删除schema下所有对象,清空Schema中所有对象的步骤
  5. shell 批量修改文件名字
  6. Java SE 正则表达式 API Pattern 与 Matcher.
  7. 从零开始做一个开源项目 学习笔记
  8. JS 正则表达式基础
  9. 集合代码----小练习3
  10. 析构函数的标量与矢量?