bg5
2015-03-25 19:14:55
Introduction:
VariantInvoke is powerfull tool inbuilt in Simba, which lets you to pass, as an argument, one function to another function and call it repeatedly inside it's body. It's LAPE equivalent of PascalScript's CallFunc().
Syntax:
Variant is very neat thing - it's basically a type, which can contain value of any basic type , such as: integer, byte ,string ,extended. Also, you can assign any basic type to Variant directly, without any casting (so be carefull here):
In VariantInvoke we use TVariantArray to store all arguments of function we call. And the result of VariantInvoke() is stored in Variant. Let's see an example, how it works:
It will print:
Limits:
As I've said already Variant can store only basic types. That makes it useless with functions dealing with TPoints ,TPointArrays, TIntegerArrays etc. ( all arrays, records , custom types at all), which are quite frequent in SRL. Furthermore, due to way how VariantInvoke works ( it runs through code before compiler, I won't go further on this topic) it can't invoke functions, which are methods of types ,such as:
Reassuming, there are 3 limits of VariantInvoke():
In the next part I will show and explain how to go around each of those, so you can use it freely with SRL and other libs.
VariantInvoke is powerfull tool inbuilt in Simba, which lets you to pass, as an argument, one function to another function and call it repeatedly inside it's body. It's LAPE equivalent of PascalScript's CallFunc().
Syntax:
function VariantInvoke('functionToInvoke': string; parametersOfFunction :TVariantArray) : Variant;Variant is very neat thing - it's basically a type, which can contain value of any basic type , such as: integer, byte ,string ,extended. Also, you can assign any basic type to Variant directly, without any casting (so be carefull here):
var i:integer;
var v : variant;
var s :string;
begin
v := 50;
i := v; // no problem
s := v; // compiler won't complain but you will get here error or access violation
end;So array of Variant ( = TVariantArray) can contain many values of different type, such as:var va : TVariantArray;
i : integer;
begin
va := ['Hello', 0.35 , 76543, i ];
end;In VariantInvoke we use TVariantArray to store all arguments of function we call. And the result of VariantInvoke() is stored in Variant. Let's see an example, how it works:
function MyNumber ( s :string; a,b :integer ) : integer;
begin
writeln(s +' args: ' + tostr(a)+ ' '+ tostr(b));
result := a*b;
end;
procedure VariantTest(f:string;va:TVariantArray;howmany : integer);
var i,r : integer;
begin
for i := 0 to howmany-1 do
begin
va[1] := va[1] * 2;
r := VariantInvoke(f,va);
writeln('Result : '+tostr(r));
end;
end;
begin
VariantTest('MyNumber',['Hello',5,7],6);
end. It will print:
Hello args: 10 7
Result : 70
Hello args: 20 7
Result : 140
Hello args: 40 7
Result : 280
Hello args: 80 7
Result : 560
Hello args: 160 7
Result : 1120
Hello args: 320 7
Result : 2240Limits:
As I've said already Variant can store only basic types. That makes it useless with functions dealing with TPoints ,TPointArrays, TIntegerArrays etc. ( all arrays, records , custom types at all), which are quite frequent in SRL. Furthermore, due to way how VariantInvoke works ( it runs through code before compiler, I won't go further on this topic) it can't invoke functions, which are methods of types ,such as:
customType.anyFunc();
tabBackpack.isFull();
TRSGameTabs.isTabVisible();
TSomething.anything.objectX.getMyValue();
which is a big pain, because SRL-6 and many other libraries are object-oriented.Reassuming, there are 3 limits of VariantInvoke():
- Functions, which return non-basic type
- Functions, which have non-basic types as parameters
- Type.function()
In the next part I will show and explain how to go around each of those, so you can use it freely with SRL and other libs.