如果我只有类/ VMT地址,如何获取类的单元名称

时间:2012-06-30 10:32:04

标签: delphi

当我阅读here时,

  

VMT还包含许多支持功能的“魔术”字段   例如父类链接,实例大小,类名,动态方法   表,发布方法表,发布字段表,RTTI表,   魔术字段的初始化表,不推荐使用的OLE自动化   调度表和实现的接口表

看起来VMT不包含包含定义类的单元名称的字段。是否涉及一些“编译魔术”?

3 个答案:

答案 0 :(得分:10)

我不明白为什么VMT应该参与其中。 TObject已经公开了class function UnitName

System.TObject.UnitName

答案 1 :(得分:1)

VMT包含指向类RTTI的指针(由ClassInfo方法提供); class RTTI包括类单元名称。作为练习,您可以从VMT指针获取单元名称,我已经写过(在Delphi 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 :(得分: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;

请注意,必须针对 nil 测试ClassInfo。例如。 SysUtils.ERangeError没有它。