4

我正在尝试使用 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;
  //...

有谁知道为什么这不起作用?有没有办法解决我的问题?提前致谢!

4

4 回答 4

7

这是您发现的一种奇怪行为。您可以使用以下方法找到类型:

RType := ctx.GetType(TypeInfo(IMyPrettyLittleInterface));

但是一旦你这样做了,你就可以按名称访问它,所以如果你需要按名称访问它,你可以执行以下操作来使其工作。

示例程序:

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.
于 2010-06-08T16:08:30.117 回答
7

问题是 VMT 和实现接口的类的 typeinfo 都不包含对这些接口的 typeinfo 的任何引用。如果程序中没有另外引用,则连接器会消除接口的类型信息。要解决此问题,需要更改类型信息格式以使类引用已实现接口的类型信息,否则所有接口都需要强链接到可执行文件中。由于编译器的集成智能链接器的工作方式,其他类型的修复,例如由链接入类实现的强链接接口,实际上没有在类类型信息中包含引用,因此存在问题。

解决此问题的另一种方法是使用指令{$STRONGLINKTYPES ON}。这将导致 EXE、BPL 或 DLL 的根类型表(让 RTL 将限定名称映射到类型的索引)中的所有类型都链接到强修正而不是弱修正。只有弱修正引用它们的符号会被智能链接器消除;如果一个或多个强修复引用了该符号,那么它将包含在最终的二进制文件中,并且弱引用不会被 nil'ed(实际上是 @PointerToNil)。

如其他答案中所述,TypeInfo(ITheInterface)在非死代码中解决了问题;这是因为 TypeInfo() 魔术函数创建了一个强大的接口修复。

于 2010-06-17T16:50:50.477 回答
0

IMyPrettyLittleInterface 是否有 GUID?如果没有,我认为 RTTI 系统不会识别它。

于 2010-06-08T13:42:01.877 回答
0

RTTI 是为在$M开关处于活动状态时声明的类型生成的。像所有编译器指令一样,该开关具有每个单元的范围。您在 DPR 文件中设置它,但该设置在您声明类型的单元中无效。

在您的接口和类声明之前设置该开关:

type
  {$M+}
  IMyPrettyLittleInterface = interface
    ['{6F89487E-5BB7-42FC-A760-38DA2329E0C5}']
  end;
  TMyIntfClass = class(TInterfacedObject, IMyPrettyLittleInterface)
  end;
于 2010-06-08T14:45:25.380 回答