Вопрос по – Delphi - вызывать метод записи по имени

7

Я написал язык сценариев для своих приложений, и моя цель - сделать возможным публиковать в скрипте любой тип из delphi. Я использую RTI для автоматизации этой задачи. Для любого типа экземпляра, такого как классы, я использую следующий код, чтобы найти и вызвать метод из скрипта.

<code>var  Info : TRttiType;  
     Meth : TRttiMethod;  
     Param : TArray<TValue>;  
     Result : TValue;  
     AnyClass : TClass;   
begin  
  ...  
  Info := RttiContext.GetType(AnyClass);  
  Meth := Info.GetMethod('AMethod');  
  Setlength(Param, 1);  
  Param[0] := TValue.From<Integer>(11);  
  Result := Meth.Invoke(ClassInstance, Param);  
  ...  
end;  
</code>

Но с записью этот код не работает, потому что тип TRttiMethod не предлагает метод Invoke () для типов записей. Я могу получить доступ к информации о методе с помощью Info.GetMethod («AMethod») из типа записи.
Например, у меня есть такая запись:

<code>TRecordType = record  
  Field1, Field2 : single;  
  procedure Calc(Value : integer);   
end;  
</code>

Так кто-нибудь знает способ вызвать метод из записи, если у меня есть methodname или methodaddress?

Хорошо, RTTI для методов записи был введен в XE2. См примерTRttiRecordType_(Delphi). LU RD
Я думал, что DWScript может сделать все это, но, возможно, я ошибаюсь David Heffernan
Вы только что изобрелиDWScript? David Heffernan
Просто ответ от Барри Келли здесь в SO, заявляющий, что нет RTTI для методов на записях:Delphi - RTTI info about methods in records. LU RD
Спасибо за подсказку, но я знаю DWScript. Мой язык предназначен в качестве скриптового интерфейса к программе на Delphi, где возможны такие конструкции, как AObject.AFunction.AObject.DoSomething. DragonFlyOfGold

Ваш Ответ

1   ответ
12

размещенной в комментариях выше, я более подробно рассмотрел тип delphi TRttiRecordMethod в System.Rtti. Он предоставляет метод DispatchInvoke (), и этот метод ожидает указатель. Так работает следующий код:

TRecordType = record   
  Field1, Field2 : single;   
  procedure Calc(Value : integer);    
end; 


  Meth : TRttiMethod; 
  Para : TRttiParameter; 
  Param : TArray<TValue>; 
  ARec : TRecordType; 
begin 
  Info := RttiContext.GetType(TypeInfo(TRecordType)); 
  Meth := Info.GetMethod('Calc'); 
  Setlength(Param, 1); 
  Param[0] := TValue.From<Integer>(12); 
  Meth.Invoke(TValue.From<Pointer>(@ARec), Param); 
end; 

Если вы хотите вызвать статический метод или перегруженный оператор, код не работает. Delphi внутренне всегда добавляет собственный указатель в список параметров, но это приведет к нарушению прав доступа. Так что используйте этот код вместо:

  Meth : TRttiMethod; 
  Para : TRttiParameter; 
  Param : TArray<TValue>; 
  ARec : TRecordType; 
begin 
  Info := RttiContext.GetType(TypeInfo(TRecordType)); 
  Meth := Info.GetMethod('&op_Addition'); 
  ... 
  Meth.Invoke(TValue.From<Pointer>(@ARec), Param); 
  Result := System.Rtti.Invoke(Meth.CodeAddress, Param, Meth.CallingConvention, Meth.ReturnType.Handle, Meth.IsStatic); 
end;    
Спасибо, это действительно помогло мне в поиске способа динамического вызова веб-службы SOAP!

Похожие вопросы