Delphi.NET 内部实现分析(3.1)

Delphi.NET 内部实现分析(3.1)

2. Borland.Delphi.System

2.1. 
简介

  
与传统 Delphi 程序编译时默认包含 System 单元类似, Delphi.NET 程序编译时默认保护了
Borland.Delphi.System
单元,而此单元中集中了诸多基础之基础的类和函数的定义、实现。
Delphi 不同的是,目前 Delphi.NET 的预览版中, Borland.Delphi.System 还只是包含了
相对基本的功能,如 TObject 类及其相关辅助函数、以及一些基础的函数,特别是很多带下划线
前缀的函数,根本就是由编译器一级固化支持,如标准输入输出函数中的 WriteLn 以及字符串处理函数等等。
下面我们来一点点分析这个最基础的单元: Borland.Delphi.System

2.2. 
元类

  
语言的发展历程,就是对问题域的抽象层面的逐渐提升的过程。在 Delphi C# 以及 Java 这些
现代语言中,一个很重要的特性就是对 RTTI  运行时类型信息的支持,而且支持将越来越完善。
Delphi
在这方面一个实例就是元类的概念的运用,用以对类的信息进一步抽象。
  
关于元类的概念以及使用,已经有大量书籍论述过,这里不再多说,让我们来看看实现。
  
在传统 Delphi Object Pascal 语言中,元类在实现上实际上就是一张 VMT(Virtual Method Table
虚方法表 ) ,在 System 单元的定义中可以详细看到其含义
//-----------------------------------------System.pas--
{ Virtual method table entries }

  vmtSelfPtr           = -76;
  vmtIntfTable         = -72;
  vmtAutoTable         = -68;
  vmtInitTable         = -64;
  vmtTypeInfo          = -60;
  vmtFieldTable        = -56;
  vmtMethodTable       = -52;
  vmtDynamicTable      = -48;
  vmtClassName         = -44;
  vmtInstanceSize      = -40;
  vmtParent            = -36;
  vmtSafeCallException = -32 deprecated;  // don't use these constants.
  vmtAfterConstruction = -28 deprecated;  // use VMTOFFSET in asm code instead
  vmtBeforeDestruction = -24 deprecated;
  vmtDispatch          = -20 deprecated;
  vmtDefaultHandler    = -16 deprecated;
  vmtNewInstance       = -12 deprecated;
  vmtFreeInstance      = -8 deprecated;
  vmtDestroy           = -4 deprecated;
//-----------------------------------------System.pas--
  
普通对象的第一个双字就是指向其类的 VMT 的指针,以此将对象、类和元类关联起来。
这个 VMT 表是 Delphi 中类的核心所在,通过它可以在运行时获取类的绝大部分信息。
例如在 VMT 中有一个 vmtSelfPtr 指针又回指到 VMT 表头,我们可以利用这个特性判断一个
指针指向的是否是有效的对象或类。 JCL 项目中有代码如下
//-----------------------------------------JclSysUtils.pas--
function IsClass(Address: Pointer): Boolean; assembler;
asm
        CMP     Address, Address.vmtSelfPtr
        JNZ     @False
        MOV     Result, True
        JMP     @Exit
@False:
        MOV     Result, False
@Exit:
end;

function IsObject(Address: Pointer): Boolean; assembler;
asm
// or IsClass(Pointer(Address^));
        MOV     EAX, [Address]
        CMP     EAX, EAX.vmtSelfPtr
        JNZ     @False
        MOV     Result, True
        JMP     @Exit
@False:
        MOV     Result, False
@Exit:
end;
//-----------------------------------------JclSysUtils.pas--
  
通过 VMT 中其它的域可以完成更多奇妙的功能,如 D6 开始对 SOAP 支持在实现上,
就是通过 VMT 动态查表完成 SOAP 函数调用到 Delphi 接口的函数调用转发的。
  
而在 Delphi.NET 中,因为 Borland 无法控制类在内存中的组织方式,因而只能
通过前面提到的 class helper 的补丁方式,让 CLR BCL System.Object 使用上
看起来象 TObject 。这样的确能够在很大程度上提供源代码级兼容性,但对 JclSysUtils
这样的 Hacker 代码就无能为力了  :)
  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值