2009-04-17 5 views
12

В файле System.pas содержится достаточное количество информации о смещенных смещениях VMT, но, похоже, он фактически не говорит о структуре самого VMT. Мне бы хотелось узнать, есть ли способ узнать размер VMT во время выполнения, или, другими словами, сколько виртуальных методов существует для данного класса?Где я могу найти информацию о структуре Delphi VMT?

ответ

13

Как насчет структуры VMT, которую вы хотите знать? Вы также знаете, что это внутренняя деталь реализации, которая может быть изменена (и со временем изменилась).

Чтобы ответить на конкретный вопрос, вот простой способ найти количество виртуальных методов данного класса:

function GetVirtualMethodCount(AClass: TClass): Integer; 
begin 
    Result := (PInteger(Integer(AClass) + vmtClassName)^ - 
    (Integer(AClass) + vmtParent) - SizeOf(Pointer)) div SizeOf(Pointer); 
end; 

Это работает, потому что я знаю, что строка, представляющая имя класса помещается сразу после всех векторов виртуальных методов в VMT.

Я также знаю, что существует 11 виртуальных методов (для D2009, 9 для D2007 и ранее) для всех TObject, которые отрицательно смещены от самого указателя VMT.

В этом причина ссылки vmtParent.

Наконец, используя ссылку класса TClass, вы можете передать любой производный класс TObject в эту функцию и получить количество виртуальных методов.

+0

VmtEquals? Я никогда не слышал об этом раньше. Равен ли один из двух новых виртуальных методов в TObject для Delphi 2009? –

+0

Да. Полагаю, для того, чтобы некоторые вещи, связанные с Generics, работали. –

+0

Аллен: Это очень приятно! Только то, что я искал. Вы говорите, что структура может и может измениться.Какая версия (и) Delphi делает этот трюк? –

2

Googling: -P для "delphi vmt" дает this. Возможно, это дает вам начало.

+2

* Улыбка * Я люблю Hallvard! Он хорош в таких трюках. К сожалению, он определяет пользовательские виртуальные объекты как «массив [0..999]», или, другими словами, «больше, чем когда-либо понадобится». Я ищу способ найти фактический размер. –

1

я подключить свой собственный сайт для этого:

What is the virtual-method table?

Это точно, как в Delphi 2005, я думаю.

VMT не имеет никакого значения, указывающего количество указателей виртуального метода, которые он удерживает. Ничто, кроме компилятора, не должно знать эту информацию, поэтому нет причин записывать ее для использования во время выполнения.

9

Я был уверен, что у Hallvard есть что-то на VMT. Конечно же, у него есть Hack #8: Explicit VMT calls, который ссылается на Ray Lischner Секреты Delphi 2 и Delphi в двух словах.

Вот его изрубил версия ВМТ

type 
    PClass = ^TClass; 
    PSafeCallException = function (Self: TObject; ExceptObject: 
    TObject; ExceptAddr: Pointer): HResult; 
    PAfterConstruction = procedure (Self: TObject); 
    PBeforeDestruction = procedure (Self: TObject); 
    PDispatch   = procedure (Self: TObject; var Message); 
    PDefaultHandler = procedure (Self: TObject; var Message); 
    PNewInstance  = function (Self: TClass) : TObject; 
    PFreeInstance  = procedure (Self: TObject); 
    PDestroy   = procedure (Self: TObject; OuterMost: ShortInt); 
    PVmt = ^TVmt; 
    TVmt = packed record 
    SelfPtr   : TClass; 
    IntfTable   : Pointer; 
    AutoTable   : Pointer; 
    InitTable   : Pointer; 
    TypeInfo   : Pointer; 
    FieldTable  : Pointer; 
    MethodTable  : Pointer; 
    DynamicTable  : Pointer; 
    ClassName   : PShortString; 
    InstanceSize  : PLongint; 
    Parent   : PClass; 
    SafeCallException : PSafeCallException; 
    AfterConstruction : PAfterConstruction; 
    BeforeDestruction : PBeforeDestruction; 
    Dispatch   : PDispatch; 
    DefaultHandler : PDefaultHandler; 
    NewInstance  : PNewInstance; 
    FreeInstance  : PFreeInstance; 
    Destroy   : PDestroy; 
    {UserDefinedVirtuals: array[0..999] of procedure;} 
    end; 

Вы должны будете читать его статью для больше на взломе, хотя.

Смежные вопросы