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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With