如何确保RTTI可用于类,而不实例化? [英] How can I make sure RTTI is available for a class without instantiating it?

查看:191
本文介绍了如何确保RTTI可用于类,而不实例化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近在此论坛上发布了一个问题,要求提供有关在DXE2可执行文件中缺少RTTI信息。

I've recently posted a question in this forum asking for any advice regarding missing RTTI information in a DXE2 executable.

该帖子是我实际案例的一个删除版本。 RRUZ来抢救,所以被剥离的版本很快就解决了。原来的问题依然存在,所以现在我正在发布。 主:

That post was a stripped down version of my actual case. RRUZ came to the rescue, and so the stripped down version was quickly resolved. The original problem, though, is still standing, and so I'm posting it in full now. "Main":

program MissingRTTI;
{$APPTYPE CONSOLE}
uses
  System.SysUtils, RTTI, MyUnit in 'MyUnit.pas', RTTIUtil in 'RTTIUtil.pas';
var
  RHelp:  TRttiHelper;
begin
  RHelp := TRttiHelper.Create();
  if (RHelp.IsTypeFound('MyUnit.TMyClass')) then WriteLn('TMyClass was found.')
  else WriteLn('TMyClass was not found.');
  ReadLn;
  RHelp.Free();
end.

RTTIUtil.pas

unit RTTIUtil;
interface
uses
  MyUnit;
type
  TRttiHelper = class(TObject)
  public
    function IsTypeFound(TypeName: string) : boolean;
  end;
implementation
uses
  RTTI;
function TRttiHelper.IsTypeFound(TypeName: string): boolean;
var
  rCtx:   TRttiContext;
  rType:  TRttiType;
begin
  Result := false;
  rCtx := TRttiContext.Create();
  rType := rCtx.FindType(TypeName);
  if (rType <> nil) then
    Result := true;
  rCtx.Free();
end;
end.

最后 MyUnit.pas 单位MyUnit; p>

and finally MyUnit.pas:

unit MyUnit;
interface
type
  TMyClass = class(TObject)
  end;
implementation
end.

找不到所需的类型。但是,如果我更改 TRttiHelper.IsTypeFound ,以便实例化(并立即释放) TMyClass 的实例,则类型被发现。像这样:

The desired type is not found. However, if I change TRttiHelper.IsTypeFound so that it instantiates (and immediately frees) an instance of TMyClass, the type is found. Like so:

function TRttiHelper.IsTypeFound(TypeName: string): boolean;
var
  rCtx:   TRttiContext;
  rType:  TRttiType;
  MyObj:  TMyClass;
begin
  Result := false;
  MyObj:= TMyClass.Create();
  MyObj.Free();
  rCtx := TRttiContext.Create();
  ...

所以我想知道,有什么办法可以强制RTTI要发送 TMyClass 而不实际实例化?

So I'm wondering, is there any way I can force RTTI to be emitted for TMyClass without actually instantiating it?

更新:

在某方面,我可能会提到,如果我尝试使用 TRttiContext.GetType 获取TRttiType,则所需的类型。所以有一些RTTI发射。检查由 TRttiContext.GetType 检索的 TRttiType.IsPublic 属性产生一个真实值,即检索到的类型是public因此应该可以使用 TRttiContext.FindType 来定位。

On a side not, I might mention that if I try to fetch the TRttiType using TRttiContext.GetType, the desired type is found. So there is some RTTI emitted. Checking the TRttiType.IsPublic property as retrieved by TRttiContext.GetType yields a true value, i.e. the retrieved type is public (and hence should be possible to locate using TRttiContext.FindType).

推荐答案

添加对类的引用,并确保编译器/链接器不能从可执行文件中删除它。

Add a reference to the class and make sure that the compiler/linker cannot strip it from the executable.

unit MyUnit;

interface

type
  TMyClass = class(TObject)
  end;

implementation 

procedure ForceReferenceToClass(C: TClass);
begin
end;

initialization
  ForceReferenceToClass(TMyClass);

end.

在生产代码中,您需要放置 ForceReferenceToClass 在一个基本单位,以便它可以共享。声明该类的单元的初始化部分是调用 ForceReferenceToClass 的最自然的地方,因为该单元是自包含的。

In production code you would want to place ForceReferenceToClass in a base unit so that it could be shared. The initialization section of the unit that declares the class is the most natural place for the calls to ForceReferenceToClass since the unit is then self-contained.

关于您的观察结果, GetType 可以找到类型,调用 GetType(TMyClass)添加对程序类型的引用。这不是RTTI存在,而 FindType 找不到。相反,包含 GetType(TMyClass)将RTTI添加到生成的程序中。

Regarding your observation that GetType can locate the type, the very act of calling GetType(TMyClass) adds a reference to the type to the program. It's not that the RTTI is present and FindType cannot find it. Rather, the inclusion of GetType(TMyClass) adds the RTTI to the resulting program.

这篇关于如何确保RTTI可用于类,而不实例化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆