如何确保RTTI可用于类,而不实例化? [英] How can I make sure RTTI is available for a class without instantiating it?
问题描述
我最近在此论坛上发布了一个问题,要求提供有关在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屋!