【问题标题】:Delphi - Invoke Record method per nameDelphi - 每个名称调用记录方法
【发布时间】:2012-04-17 13:48:38
【问题描述】:

我为我的应用程序编写了一种脚本语言,我的目标是使从 delphi 中发布任何类型的脚本成为可能。我使用 rtti 来自动化这个任务。对于像类这样的任何实例类型,我使用以下代码从脚本中查找和调​​用方法。

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;  

但是对于记录,此代码不起作用,因为 TRttiMethod 类型不为记录类型提供 Invoke() 方法。我可以通过 Info.GetMethod('AMethod') 从记录类型中访问方法信息。
例如我有这样的记录:

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

如果我有方法名或方法地址,那么有人知道如何从记录中调用方法吗?

【问题讨论】:

  • 你刚刚是不是重新发明了DWScript
  • 感谢您的提示,但我知道 DWScript。我的语言旨在作为 delphi 程序的可编写脚本的接口,其中 AObject.AFunction.AObject.DoSomething 之类的构造是可能的。
  • 我以为 DWScript 可以做到这一切,但也许我错了
  • 巴里·凯利 (Barry Kelly) 在 SO 的回答中指出记录中的方法没有 RTTI:Delphi - RTTI info about methods in records
  • 好的,XE2 中引入了记录方法的 RTTI。参见示例TRttiRecordType_(Delphi)

标签: delphi record rtti


【解决方案1】:

在浏览了上面 cmets 中发布的 delphi 文档中的链接后,我仔细查看了 System.Rtti 中的 delphi 类型 TRttiRecordMethod。它提供了 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 在内部总是将 self 指针添加到参数列表,但这会导致访问冲突。所以改用这段代码:

  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 Web 服务的方法!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-19
相关资源
最近更新 更多