【发布时间】:2012-06-30 10:32:04
【问题描述】:
当我读到here,
VMT 还包含许多“神奇”字段来支持功能 如父类链接、实例大小、类名、动态方法 表、已发布方法表、已发布字段表、RTTI 表、 魔术字段的初始化表,已弃用的 OLE 自动化 调度表和实现接口表
看起来 VMT 不包含包含定义类的单元名称的字段。是否涉及一些“编译器魔法”?
【问题讨论】:
标签: delphi
当我读到here,
VMT 还包含许多“神奇”字段来支持功能 如父类链接、实例大小、类名、动态方法 表、已发布方法表、已发布字段表、RTTI 表、 魔术字段的初始化表,已弃用的 OLE 自动化 调度表和实现接口表
看起来 VMT 不包含包含定义类的单元名称的字段。是否涉及一些“编译器魔法”?
【问题讨论】:
标签: delphi
我不明白为什么 VMT 应该参与其中。 TObject 已经为此公开了一个class function UnitName。
【讨论】:
typinfo.GetTypeData(TSomeClass.ClassInfo).UnitName
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;
【讨论】:
ClassInfo 方法获得,你为什么要演示这样一个迂回的路线来获得相同的信息?您可以简单地用 P := TObj.ClassInfo 替换所有这些代码。
ClassInfo 方法,只有一个指向未知类的 VMT 的指针。您可能会尝试以某种方式对 VMT 指针进行类型转换,但我还没有找到方法。
TClass。然后你可以做一个单行:TypInfo.GetTypeData(TClass(vmt).ClassInfo).UnitName
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 没有。
【讨论】: