【问题标题】:How can I get the unit name of a class if I have the class / VMT address only如果我只有班级/VMT 地址,如何获取班级的单位名称
【发布时间】:2012-06-30 10:32:04
【问题描述】:

当我读到here

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

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

【问题讨论】:

    标签: delphi


    【解决方案1】:

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

    System.TObject.UnitName

    【讨论】:

    • 对于D2009之前的版本,可以使用typinfo.GetTypeData(TSomeClass.ClassInfo).UnitName
    【解决方案2】:

    VMT 包含一个指向 RTTI 类的指针(由ClassInfo 方法提供);类 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;
    

    【讨论】:

    • 既然,正如你提到的,RTTI 指针可以从ClassInfo 方法获得,你为什么要演示这样一个迂回的路线来获得相同的信息?您可以简单地用 P := TObj.ClassInfo 替换所有这些代码。
    • @RobKennedy - 你不能直接调用 ClassInfo 方法,只有一个指向未知类的 VMT 的指针。您可能会尝试以某种方式对 VMT 指针进行类型转换,但我还没有找到方法。
    • @Serg 只需将 vmt 指针转换为 TClass。然后你可以做一个单行:TypInfo.GetTypeData(TClass(vmt).ClassInfo).UnitName
    • 但是您首先是如何以及为什么获得指向 VMT 的原始指针?直接使用类引用或对象引用即可。您甚至根本不需要任何有关“VMT”概念的知识。
    【解决方案3】:
    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 进行 nil 测试。例如。 SysUtils.ERangeError 没有。

    【讨论】:

      猜你喜欢
      • 2011-05-26
      • 1970-01-01
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      • 1970-01-01
      • 2021-11-18
      相关资源
      最近更新 更多