[英]How do I get the number of entries (virtual methods) in the VMT?
At positive offsets the VMT stores pointers to all user defined virtual methods. VMT以正偏移量存储指向所有用户定义的虚拟方法的指针。
I need to write some code to hook the VMT. 我需要编写一些代码来挂接VMT。 The way I do this is to get a pointer to a virtual method in an ancestor class. 我这样做的方法是获得一个指向祖先类中的虚拟方法的指针。
Let's say: TCustomForm.ShowModal
. 假设: TCustomForm.ShowModal
。 I then look up the offset in the VMT of TCustomForm
. 然后,我在TCustomForm
的VMT中TCustomForm
偏移量。 With this offset in hand I go to TMyForm
and alter its VMT to point to the function I need. 有了这个偏移量后,我转到TMyForm
并更改其VMT以指向我需要的功能。
I would like to generalize the approach and in order to do so I would like to know the total number of entries the VMT holds so I don't search past the end. 我想归纳一下这种方法,为了做到这一点,我想知道VMT持有的条目总数,所以我不会在最后搜索。
How do I obtain the size of the (user definable part of) the VMT? 如何获得VMT(用户可定义的部分)的尺寸?
Digging through the RTL source I think this is the way to get the count: 挖掘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;
Feel free to correct me if needed. 如有需要,请随时纠正我。
A way to do this without much actual knowledge of the VMT structure, and hence less prone to breaking when the VMT structure changes again, is using the Rtti for this. 一种在没有太多VMT结构实际知识的情况下执行此操作的方法,因此在VMT结构再次更改时不太容易发生损坏,为此使用了Rtti。 TRttiInstanceType
knows the VmtSize
of the associated class. TRttiInstanceType
知道关联类的VmtSize
。
So using VmtSize
and a VMT entry being a Pointer
因此,使用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;
This will however include all entries inherited from the base class(es) too. 但是,这也将包括所有从基类继承的条目。 Including the ones from TObject
at negative offsets. 包括来自TObject
的负偏移量的对象。 But it is possible to subtract all entries from a given base class, eg TObject
. 但是可以从给定的基类(例如TObject
减去所有条目。 Here is an approach with a variable base class provided: 这是提供可变基类的一种方法:
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;
And : When using Jedi there is a function in JclSysUtils
called GetVirtualMethodCount
. 并且 :使用Jedi时 , JclSysUtils
有一个名为GetVirtualMethodCount
的函数。 Although I'm not sure if this is up-to-date and correct. 尽管我不确定这是否是最新和正确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.