Delphi TRttiType.GetMethods возвращает ноль экземпляров TRttiMethod

Недавно мне удалось получить TRttiType для интерфейса с помощью TRttiContext.FindType с помощью Robert Loves «GetType» — обходной путь («регистрация» интерфейса явным вызовом ctx.GetType, например, RType := ctx.GetType(TypeInfo(IMyPrettyLittleInterface));).

Следующим логическим шагом будет повторение методов указанного интерфейса. Рассмотреть возможность

program rtti_sb_1;
{$APPTYPE CONSOLE}
uses
  SysUtils, Rtti, mynamespace in 'mynamespace.pas';
var
  ctx:      TRttiContext;
  RType:    TRttiType;
  Method:   TRttiMethod;
begin
  ctx := TRttiContext.Create;
  RType := ctx.GetType(TypeInfo(IMyPrettyLittleInterface));
  if RType <> nil then begin
    for Method in RType.GetMethods do
      WriteLn(Method.Name);
  end;
  ReadLn;
end.

На этот раз мой mynamespace.pas выглядит так:

IMyPrettyLittleInterface = interface
  ['{6F89487E-5BB7-42FC-A760-38DA2329E0C5}']
  procedure SomeProcedure;
end;

К сожалению, RType.GetMethods возвращает экземпляр TArray нулевой длины. Есть ли у кого-нибудь возможность воспроизвести мои проблемы? (Обратите внимание, что в моем примере я явно извлек TRttiType, используя TRttiContext.GetType, а не обходной путь; введение включено, чтобы предупредить читателей о том, что могут быть некоторые нерешенные проблемы, связанные с rtti и интерфейсами.) Спасибо!


person conciliator    schedule 09.06.2010    source источник


Ответы (3)


Я только что проследил, что происходит, и в TRttiInterfaceType.Create, строка 5774, написано:

hasRtti := ReadU16(P);
if hasRtti = $FFFF then
  Exit;

И в вашем интерфейсе, и в IInterface, от которого он наследуется, HasRtti читается как $FFFF. Таким образом, очевидно, что для методов интерфейса не генерируется RTTI, и это справедливо даже для базового типа интерфейса. Я не знаю почему. Не уверен, кто мог бы знать почему, кроме Барри Келли.

person Mason Wheeler    schedule 09.06.2010
comment
Вау Мейсон; вы достаточно смелы, чтобы углубиться в настоящий источник. Я думаю, я мог бы попробовать это сам, если бы не мое понимание кода. Он сломался с тех пор, как я обновился с D2009... :| Большое спасибо! Думаю, мне лучше сообщить об этом QC. - person conciliator; 09.06.2010
comment
@Conciliator: Мужественный? Неа. RTL на самом деле довольно красив, по большей части. Большинство действительно страшных вещей находится в system.pas. :П - person Mason Wheeler; 09.06.2010
comment
:) Я сообщил об этом как QC #85308; пытаясь взломать его, пока мы говорим. - person conciliator; 10.06.2010
comment
@conciliator, почему отчет был отозван? qc.embarcadero.com/wc/qcmain.aspx?d=85308 - person Jeroen Wiert Pluimers; 17.07.2013
comment
@JeroenWiertPluimers, правда, не знает. Я точно этого не делал. Я посмотрю на это, когда я вернусь в офис в понедельник. - person conciliator; 17.07.2013

Существуют определенные директивы компилятора, иногда необходимые для генерации RTTI, например M+. Возможно, вам просто нужно установить один из них?

person Dave Novo    schedule 09.06.2010
comment
По-видимому, $M+ не нужен в D2010 (о чем я, наверное, забыл сказать, что использую). - person conciliator; 09.06.2010

В конце концов, Дэйв был прав. Оказывается, интерфейс должен быть окружен предложением {$M+}/{$M-}. Компиляция с

{$M+}
IMyPrettyLittleInterface = interface
  ['{6F89487E-5BB7-42FC-A760-38DA2329E0C5}']
  procedure SomeProcedure;
end;
{$M-}

Имеет ли это.

person conciliator    schedule 10.06.2010