我为我的应用程序编写了一个脚本语言,我的目标是可以在脚本中发布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;
解决方法
在探索上面评论中发布的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内部总是将自指针添加到参数列表,但这会导致访问.所以请使用此代码:
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;