1

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

我想概括一下这种方法,为了做到这一点,我想知道 VMT 拥有的条目总数,所以我不会搜索到最后。

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

4

2 回答 2

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;

然而,这也将包括从基类继承的所有条目。包括来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;

并且:当使用JediJclSysUtils时,调用了一个函数GetVirtualMethodCount。虽然我不确定这是否是最新的和正确的。

于 2017-08-21T12:47:48.387 回答
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;

如果需要,请随时纠正我。

于 2017-08-21T12:03:41.233 回答