我正在尝试使用D2010 RTTI获取接口。
program rtti_sb_1;
{$APPTYPE CONSOLE}
{$M+}
uses
SysUtils,
Rtti,
mynamespace in 'mynamespace.pas';
var
ctx: TRttiContext;
RType: TRttiType;
MyClass: TMyIntfClass;
begin
ctx := TRttiContext.Create;
MyClass := TMyIntfClass.Create;
// This prints a list of all known types, including some interfaces.
// Unfortunately, IMyPrettyLittleInterface doesn't seem to be one of them.
for RType in ctx.GetTypes do
WriteLn(RType.Name);
// Finding the class implementing the interface is easy.
RType := ctx.FindType('mynamespace.TMyIntfClass');
// Finding the interface itself is not.
RType := ctx.FindType('mynamespace.IMyPrettyLittleInterface');
MyClass.Free;
ReadLn;
end.
IMyPrettyLittleInterface
和TMyIntfClass = class(TInterfacedObject, IMyPrettyLittleInterface)
都在mynamespace.pas
中声明,特别是
unit mynamespace;
interface
type
IMyPrettyLittleInterface = interface
['{6F89487E-5BB7-42FC-A760-38DA2329E0C5}']
end;
TMyIntfClass = class(TInterfacedObject, IMyPrettyLittleInterface)
end;
//...
有谁知道为什么这不起作用?有办法解决我的问题吗?提前致谢!
答案 0 :(得分:7)
这是您发现的一种奇怪行为。您可以使用以下方式找到类型:
RType := ctx.GetType(TypeInfo(IMyPrettyLittleInterface));
但是,在您完成此操作后,您可以按名称访问它,因此如果您需要通过Name访问它,您可以执行以下操作以使其正常工作。
示例程序:
program Project1;
{$APPTYPE CONSOLE}
uses
SysUtils,
Rtti,
TypInfo,
Unit1 in 'Unit1.pas';
var
ctx : TRttiContext;
IType : TRttiType;
begin;
ctx := TRttiContext.Create;
IType := ctx.FindType('Unit1.IExample');
if Assigned(IType) then
begin
writeln('Found');
Writeln(IType.QualifiedName);
end
else
writeln('Not Found');
ReadLn;
end.
示例单位:
unit Unit1;
interface
type
IExample = interface
['{D61F3245-13FB-44BF-A89D-BB358FAE7D19}']
end;
implementation
uses Rtti;
var
C : TRttiContext;
initialization
C.GetType(TypeInfo(IExample));
end.
答案 1 :(得分:7)
问题是VMT和实现接口的类的typeinfo都不包含对这些接口的typeinfo的任何引用。然后,如果程序中没有另外引用,则链接器将消除接口的typeinfo。要解决这个问题,需要对类进行typeinfo格式更改以引用已实现的接口的typeinfo,否则所有接口都需要强烈链接到可执行文件中。其他类型的修复,例如由链接类实现而不实际包含类typeinfo中的引用的强链接接口,由于编译器的集成智能链接器的工作方式而存在问题。
解决此问题的另一种方法是使用指令{$STRONGLINKTYPES ON}
。这将导致EXE,BPL或DLL的根类型表中的所有类型(允许RTL将限定名称映射到类型的索引)与强修正而不是弱修复相关联。智能链接器消除了只有弱修正引用它们的符号;如果一个或多个强大的修正引用了该符号,那么它将包含在最终的二进制中,并且弱引用不会被取消(实际上是@PointerToNil)。
如其他答案中所述,非死代码中的TypeInfo(ITheInterface)
修复了问题;这是因为TypeInfo()魔术函数为接口创建了强大的修正。
答案 2 :(得分:0)
IMyPrettyLittleInterface是否有GUID?如果不这样做,我认为RTTI系统不会识别它。
答案 3 :(得分:0)
为$M
开关处于活动状态时声明的类型生成RTTI。与所有编译器指令一样,该开关具有 per-unit 范围。您在DPR文件中设置它,但该设置对您声明类型的单位没有影响。
在接口和类声明之前设置该开关:
type
{$M+}
IMyPrettyLittleInterface = interface
['{6F89487E-5BB7-42FC-A760-38DA2329E0C5}']
end;
TMyIntfClass = class(TInterfacedObject, IMyPrettyLittleInterface)
end;