SRL Archive - OSR Help

TVariantArray Help


zzzooo

2014-10-08 21:00:21

I'm having the same problem as this thread, villavu.com/forum/showthread.php?t=96695 (Can't post links).
However the solution didn't work. I am getting an error, any ideas?
Error: Invalid evaluation at line args := [text];

function WaitChatMessage(text: TStringArray; time: integer): boolean;
var
args: TVariantArray;
begin
args := [text];
Result := WaitFuncEx('FindBlackChatMessageEx', args, 20 + Random(20), time);
end;

Brandon

2014-10-08 21:02:49

From: zzzooo
..
args := [text];



You're assigning a 2-Dimensional Array of "string" to a 1-Dimensional array of Variant.

zzzooo

2014-10-08 21:05:19

If you look at the link I posted, I've tried using that exact solution, still got the error.
And the array text, is an one dimensional array of text ex:
text := ['dog', 'food', 'is', 'awesome'];

Edit: Nvm just got what you said, is there anyway to pass an the array text to the function WaitFuncEx is calling?

Brandon

2014-10-08 21:07:31

From: zzzooo
If you look at the link I posted, I've tried using that exact solution, still got the error.
And the array text, is an one dimensional array of text ex:
text := ['dog', 'food', 'is', 'awesome'];

Edit: Nvm just got what you said, is there anyway to pass an the array text to the function WaitFuncEx is calling?


Create an intermediate function like so:


//coverts TStringArray to TVariantArray
//by copying all elements to the result.
Function MakeVarr(var T: TStringArray): TVariantArray;
var
I: Integer;
begin
SetLength(Result, Length(T));
For I := 0 To High(Result) Do
Result[I] := T[I];
end;


and then use it like so:


function WaitChatMessage(text: TStringArray; time: integer): boolean;
var
args: TVariantArray;
begin
args := MakeVarr(text);
Result := WaitFuncEx('FindBlackChatMessageEx', args, 20 + Random(20), time);
end;

Is there a reason you are wrapping WaitFuncEx for TStringArray specifically though? You could easily wrap it like this (for efficiency):


function WaitChatMessage(args: TVariantArray; time: integer): boolean;
begin
Result := WaitFuncEx('FindBlackChatMessageEx', args, 20 + Random(20), time);
end;

begin
WaitChatMessage(['one', 'two', 'three', 5, 10, 'whatever'], 10000);
end.

This way you don't have to copy all your arrays into a TVariantArray..

zzzooo

2014-10-08 21:12:33

That's not what I'm trying to do. The function FindBlackChatMessageEx takes a TStringArray for an arg.

function FindBlackChatMessageEx(text: TStringArray): boolean
var
theText: string;
i: integer;
begin
theText := GetBlackChatMessage;
for i := 0 to High(text) do
Writeln(text[i]);
if (Pos(text[i], theText) > 0) then
begin
Exit(True);
end;
end;

Brandon

2014-10-08 21:43:14

From: zzzooo
That's not what I'm trying to do. The function FindBlackChatMessageEx takes a TStringArray for an arg.


Ahh that's why.. That function's signature did not exist on the github so I assumed it was just taking parameters and not an array as a parameter..

Still.. what I said isn't wrong though.. You just have to adjust it to fit your needs. If your parameters are arrays then pass a 2D array. If your parameter is a 2D array, pass a 3D array.

VariantInvoke and ThreadSafeCall both push the indices of the array as arguments to the function onto the stack. When you pass it an array, it thinks that array contains the ARGUMENTS you want to pass.. It will pass each index in that array as an argument.

Ex:


procedure CallMe(arg1, arg2, arg3: Integer);
begin
end;

procedure CallMeMaybe(arg: TIntegerArray);
begin
end;

procedure Where(YouThink: TIntegerArray; Youre: String; Going: Byte; Baby: String);
begin
end;

var
CallMeArgs: TVariantArray;
CallMeMaybeArgs: TVariantArray;
WhereArgs: TVariantArray;
begin
CallMeArgs := [1, 2, 3]; //array containing 3 Arguments for a function that accepts 3 args..
ThreadSafeCall('CallMe', CallMeArgs);

CallMeMaybeArgs := [[1, 2, 3]]; //an array containing a TIntegerArray to be passed to a function that only has one argument..
ThreadSafeCall('CallMeMaybe', CallMeMaybeArgs);

WhereArgs := [[1, 2, 3], 'hello', #32, 'world']; //an array containing a TIntegerArray, a string, a byte and another string..
ThreadSafeCall('Where', WhereArgs);
end.

If your function takes 3 args, you pass ONE array with 3 indices. If you function takes an Array, you pass it an array containing the other array.


Example:

function FindBlackChatMessageEx(text: TStringArray): boolean;
begin
writeln(text);
end;

function CallProc(s: string; params: TVariantArray): Variant;
begin
Result := ThreadSafeCall(s, params);
end;

function WaitFuncEx(Func: string; var Args: TVariantArray; WaitPerLoop, MaxWait: integer): boolean;
var
T: integer;
Temp: variant;
begin
T := GetSystemTime + MaxWait;
while (GetSystemTime < T) do
begin
Temp := CallProc(Func, Args);
Temp := ToStr(Temp);
Result := StrToBoolDef(Temp, False);
if (Result) then
Exit;
Wait(WaitPerLoop);
end;
end;


function WaitChatMessage(args: TVariantArray; time: integer): boolean;
begin
Result := WaitFuncEx('FindBlackChatMessageEx', args, 20 + Random(20), time);
end;

begin
WaitChatMessage([['one', 'two']], 1000);
end.

zzzooo

2014-10-08 21:49:51

Ok so I just realized that for this solution to work, I have to have interpreter set to pascal.
Is there anyway to make this work for Lape?

Brandon

2014-10-08 22:07:56

From: zzzooo
Ok so I just realized that for this solution to work, I have to have interpreter set to pascal.
Is there anyway to make this work for Lape?


True.. Lape has "VariantInvoke" instead of "ThreadSafeCall" but even then, Lape's Variant type does NOT support arrays..

You need to thus hack it or trick it via a cast..


function FindBlackChatMessageEx(text: PtrUInt): boolean; //this is a lie..
begin
writeln(TStringArray(text)); //cast that lie to some truth..
end;

function CallProc(s: string; params: TVariantArray): Variant;
begin
Result := VariantInvoke(s, params); //variantInvoke..
end;

function WaitFuncEx(Func: string; var Args: TVariantArray; WaitPerLoop, MaxWait: integer): boolean;
var
T: integer;
Temp: variant;
begin
T := GetSystemTime + MaxWait;
while (GetSystemTime < T) do
begin
Temp := CallProc(Func, Args);
Temp := ToStr(Temp);
Result := StrToBoolDef(Temp, False);
if (Result) then
Exit;
Wait(WaitPerLoop);
end;
end;


function WaitChatMessage(args: TVariantArray; time: integer): boolean;
begin
Result := WaitFuncEx('FindBlackChatMessageEx', args, 20 + Random(20), time);
end;

var
T: TStringArray;
begin
T := ['hello', 'world'];
WaitChatMessage([PtrUInt(T)], 1000); //cast the truth to a lie..
end.

zzzooo

2014-10-08 22:45:17

Ah okay. Thanks for all the help, got it to work finally.

bg5

2014-10-10 22:50:19


function FindBlackChatMessageEx(Msgs : string) : boolean; overload;
begin
Result := FindBlackChatMessageEx(Explode('#@#',Msgs));
end;

function WaitChatMessage(text: TStringArray; time: integer): boolean;
var
args: TVariantArray;
begin
args := [Implode('#@#',text)];
Result := WaitFuncEx('FindBlackChatMessageEx', args, 20 + Random(20), time);
end;