2017-08-20 45 views
1

在正偏移量处,VMT存储指向所有用户定义虚拟方法的指针。
我需要编写一些代码来挂钩VMT。 我这样做的方式是获取指向祖先类中的虚拟方法的指针。
比方说:TCustomForm.ShowModal。然后我查找了TCustomForm的VMT中的偏移量。有了这个偏移量,我去TMyForm并改变它的VMT指向我需要的功能。如何获取VMT中的条目数量(虚拟方法)?

我想概括一下这个方法,为了做到这一点,我想知道VMT的条目总数,所以我不会搜索结尾。

如何获取VMT(用户可定义的部分)的大小?

+1

[我在哪里可以找到有关Delphi VMT结构的信息?](https://stackoverflow.com/q/760513/576719) –

+0

我可能会误解,但在System.Rtti中有TVirtualMethodInterceptor类。有创建的ProxyClass,这可能会帮助你,因为它创建一个VMT副本,其中的一些代码可能会帮助你。我记得有点像vmtSize。 – nil

+0

@LURD,这个问题只是对这个问题的不正确答案,因为Stephan在他对这个答案的评论中指出:https://stackoverflow.com/a/761101/650492 – Johan

回答

0

通过RTL源挖我认为这是得到计数方式:

function GetVMTCount(AClass: TClass): integer; 
var 
    p: pointer; 
    VirtualMethodCount: word; 
begin 
    p := PPointer(PByte(AClass) + vmtMethodTable)^; 
    VirtualMethodCount:= PWord(p)^; 
    //Size of the VMT in bytes 
    Result:= VirtualMethodCount * SizeOf(Pointer) - vmtSelfPtr; 
    //Number of entries in the VMT 
    Result:= Result div SizeOf(Pointer); 
end; 

随意,如果需要指正。

0

在VMT结构没有太多实际知识的情况下做到这一点,并且因此在VMT结构再次改变时不太可能中断的方式是使用Rtti来实现这一点。 TRttiInstanceType知道相关类的VmtSize

因此,使用VmtSize和VMT入口是一个Pointer

function GetVirtualMethodCount(AClass: TClass): Integer; 
var 
    AContext: TRttiContext; 
    AType: TRttiType; 
begin 
    AType := AContext.GetType(AClass); 
    Result := (AType as TRttiInstanceType).VmtSize div SizeOf(Pointer); 
end; 

然而,这将包括从基类(ES)也继承所有条目。包括来自TObject的消极抵消。但是可以从给定的基类中减去所有的条目,例如TObject。这里是具有可变基类提供了一种方法:

function GetVirtualMethodCountMinusBase(AClass: TClass; ABaseClass: TClass): Integer; 
var 
    AContext: TRttiContext; 
    AType, ABaseType: TRttiType; 
begin 
    AType := AContext.GetType(AClass); 
    ABaseType := AContext.GetType(ABaseClass); 
    Result := ((AType as TRttiInstanceType).VmtSize - (ABaseType as TRttiInstanceType).VmtSize) div SizeOf(Pointer); 
end; 

:当使用存在JclSysUtils一个函数调用GetVirtualMethodCount。虽然我不确定这是否是最新和正确的。