Delphi - 每个名称调用Record方法 [英] Delphi - Invoke Record method per name

查看:529
本文介绍了Delphi - 每个名称调用Record方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

但是,由于TRttiMethod类型不提供Invoke,所以该代码不起作用()方法用于记录类型。我可以从记录类型访问Info.GetMethod('AMethod')的方法信息。

例如我有一个这样的记录:

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

所以有没有人知道如果我有methodname或methodaddress从记录调用方法? / p>

解决方案

在上述注释中发现delphi文档中的链接之后,我仔细观察了System.Rtti中的delphi类型TRttiRecordMethod 。它提供了DispatchInvoke()方法,该方法期望一个指针。
所以以下代码工作:

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


Meth:TRttiMethod;
Para:TRttiParameter;
参数: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);
结束

如果要调用静态方法或重载运算符,代码不起作用。 Delphi内部总是将self指针添加到参数列表中,但这将导致访问冲突。所以使用这个代码:

  Meth:TRttiMethod; 
Para:TRttiParameter;
参数:TArray< TValue> ;;
ARec:TRecordType;
begin
Info:= RttiContext.GetType(TypeInfo(TRecordType));
Meth:= Info.GetMethod('& op_Addition');
...
Meth.Invoke(TValue.From< Pointer>(@ ARec),Param);
结果:= System.Rtti.Invoke(Meth.CodeAddress,Param,Meth.CallingConvention,Meth.ReturnType.Handle,Meth.IsStatic);
结束


I wrote a scriptlanguage for my applications and my goal is to make it possible to publish any type from delphi in the script. I use rtti to automatize this task. For any instance type like classes I use the following code to find and call a method from script.

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;  

But with a record this code doesn't work, because the TRttiMethod type doesn't offer an Invoke() method for record types. I can access the method infos by Info.GetMethod('AMethod') from the record type.
For example i have a record like this:

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

So does anyone know a way to invoke a method from a record if i have methodname or methodaddress?

解决方案

After exploring the links in delphi documentations posted in the comments above I took a closer look at the delphi type TRttiRecordMethod in System.Rtti. It provides the method DispatchInvoke() and this method expects a pointer. So following code works:

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; 

If you want to call a static method or overloaded operator the code doesn't work. Delphi internally always add the self pointer to parameterlist, but this will cause a accessviolation. So use this code instead:

  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;    

这篇关于Delphi - 每个名称调用Record方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆