naMethod POP ECX POP EAX JE @@Abstract JMP ESI ; ESI 指向动态方法入口地址 @@Abstract: POP ECX JMP _AbstractError end; System.GetDynaMethod 则在 DMT 中寻找该动态方法的编号,如果找到了,就从 DMT 中取得该方法的入口地址;如果找不到,则继续在父类的 DMT 中寻找该方法编号直至 TObject 的 DMT(TObject 中指向 DMT 的指针为 nil,循环到这里自然会停止): procedure GetDynaMethod; { function GetDynaMethod(vmt: TClass; selector: Smallint) : Pointer; } asm { -> EAX vmt of class } { SI dynamic method index } { <- ESI pointer to routine } { ZF = 0 if found } { trashes: EAX, ECX }
PUSH EDI XCHG EAX,ESI JMP @@haveVMT @@outerLoop: MOV ESI,[ESI] @@haveVMT: MOV EDI,[ESI].vmtDynamicTable TEST EDI,EDI JE @@parent MOVZX ECX,word ptr [EDI] PUSH ECX ADD EDI,2 REPNE SCASW JE @@found POP ECX @@parent: MOV ESI,[ESI].vmtParent TEST ESI,ESI JNE @@outerLoop JMP @@exit
@@found: POP EAX ADD EAX,EAX SUB EAX,ECX { this will always clear the Z-flag ! } MOV ESI,[EDI+EAX*2-4]
@@exit: POP EDI end; 这里多说一句,看 System.GetDynaMethod 的代码简直就像在欣赏一件艺术品,代码被 Borland 的工程师优化得无可挑剔,其中用到了不少技巧,你需要慢慢体会,总之好棒! 至于象 TMyObject 中类似 WMCommand 的方法通常是由 TObject.Dispatch 来进行消息派发的,原理完全同于上面的过程,只是在 DMT 中检索的是消息 ID 而不是方法编号。具体看 TObject.Dispatch 源码及我的《Delphi 的消息机制学习笔记》。
参考文献
1. 李维.《深入核心 -- VCL架构剖析》第二章,2004.1
2. savetime."Delphi 的对象机制浅探", Jan 2004
3. 李战.《悟透delphi》之第二章 --- 《DELPHI的原子世界》
4. Ray Lischner.《Delphi in a Nutshell》,2000
上一页 [1] [2] |