2012-06-30 38 views
6

當我讀到here類/ VMT地址,我怎樣才能得到一個類的單位名稱,如果我只有

的VMT還包含了一些「神奇」領域的支持功能 如父類的鏈接,例如大小,類名,動態方法 表,公佈的方法表,出版領域的表,RTTI表,因爲魔法領域 初始化表,棄用的OLE自動化 分派表和實現的接口表

它看起來像VMT不包含包含定義類的單元名稱的字段。是否存在一些「編譯器魔術」?

回答

9

我看不出爲什麼VMT應該在這裏介入。 TObject已經爲此暴露了class function UnitName

System.TObject.UnitName

+9

對於早於D2009的版本,可以使用'typinfo.GetTypeData(TSomeClass.ClassInfo).UnitName' –

1

VMT包括一個指針,指向類RTTI(由ClassInfo方法提供);類RTTI包含一個類的單元名稱。作爲一個練習,你可以從VMT指針得到單位名稱,我寫了這個(德爾福XE測試):

uses TypInfo; 

type 
    TObj = class 

    end; 

procedure TForm1.Button3Click(Sender: TObject); 
var 
    Obj: TObj; // dummy obj instance 
    VMT: Pointer; 
    P: Pointer; // class info 

begin 
// you can get VMT pointer so 
    Obj:= TObj.Create; 
    VMT:= PPointer(Obj)^; 
    Obj.Free; 
// or so 
    VMT:= Pointer(TObj); 

    P:= PPointer(PByte(VMT) + vmtTypeInfo)^; 
    if P <> nil then 
    ShowMessage(GetTypeData(P).UnitName); 
end; 
+2

正如你所提到的那樣,RTTI指針可以從'ClassInfo'方法中使用,爲什麼你要證明這樣一個迂迴路線以獲得相同的信息?你可以用'P:= TObj.ClassInfo'替換所有的代碼。 –

+0

@RobKennedy - 你不能直接調用'ClassInfo'方法只有一個指向未知類的VMT的指針。你可能會嘗試以某種方式改寫VMT指針,但我還沒有找到如何去做。 – kludg

+4

@Serg只需將vmt指針轉換爲'TClass'即可。然後你可以做一個單行:'TypInfo.GetTypeData(TClass(vmt).ClassInfo).UnitName' –

0
procedure MessageException(E: Exception); 
var 
    TI: TypInfo.PTypeInfo; 
begin 
    TI := E.ClassInfo; 
    if Assigned(TI) then 
    begin 
    Dialogs.MessageDlg(TypInfo.GetTypeData(TI).UnitName + '.' + 
     E.ClassName + ': ' + E.Message, Dialogs.mtError, [Dialogs.mbOK], 0, Dialogs.mbOK); 
    end 
    else 
    begin 
    Dialogs.MessageDlg(E.ClassName + ': ' + E.Message, Dialogs.mtError, [Dialogs.mbOK], 0, Dialogs.mbOK); 
    end; 
end; 

注意的ClassInfo必須爲進行測試。例如。 SysUtils.ERangeError沒有它。

相關問題