SRL Archive - RS3 Help

Fun with function pointers


akarigar

2014-11-10 16:36:50

Hey guys, I was wondering if someone could point me in the right direction here. I want to achieve something like the following.

...

function exec(f: function(x: integer): boolean; x: integer);
begin
result := f(x);
end;

begin
...
writeLn(exec(@bankScreen.open, x));
end.
Of course, the above won't work. So I looked around and found this, which says to use of object. This kind of works, but doesn't. Let's take a look at the following example.

program Example;
{$DEFINE SMART}
{$i srl-6/srl.simba}

type TSimpleFunction = function(x: integer): boolean of object;

function runSimpleFunction(f: TSimpleFunction; x: integer): boolean;
begin
result := f(x);
end;

begin
clearDebug();
setupSRL();

writeLn('bankScreen.open:');
writeLn(runSimpleFunction(@bankScreen.open, BANK_CHEST_LUMBRIDGE));
writeLn('bankScreen.clickButton:');
writeLn(runSimpleFunction(@bankScreen.clickButton, BANK_BUTTON_PRESET_1));
end.
The result of running the above is:

bankScreen.open:
-- TRSBankscreen.__openChest()
---- isMouseOverText()
------ Current mouse-over text: "Use Bank chest"
------ Found "Use Bank" in mouse-over string: "Use Bank chest"
---- isMouseOverText(): True
---- Succesfully opened the bank
-- TRSBankscreen.__openChest() result = true
True
bankScreen.clickButton:
Error: Access violation at line 1173
Execution failed.
Line 1173 of bankscreen.simba is:

result := (not self.isOpen());
I would have been okay with the results if both functions failed, you know, since TRSBankScreen is a record with no apparent relation to TObject. But it doesn't do that. I'm not sure what's causing this access violation, anyone know? I have checked, self is set to bankScreen, and it exists. So my question is why is this happening? How do I get around it? Is it possible to do what I'm trying to do in Lape? Bonus question: are classes for Lape under development? Thanks in advance!

Olly

2014-11-10 16:49:38

Yes a type is a object, so 'of object' is the way to go,

1) I cannot test currently but clickButton has a default parameter and if you're calling it via pointer you need to cast it with the correct parameters, this includes default ones. ie
TSimpleFunction = function(x: Integer; b: Boolean);
2) Meh… there is always a chance but i very much doubt we will ever get a major update to Lape again, so no classes. :(

akarigar

2014-11-10 17:05:12

From: Olly

Yes a type is a object, so 'of object' is the way to go,

1) I cannot test currently but clickButton has a default parameter and if you're calling it via pointer you need to cast it with the correct parameters, this includes default ones

That's sexy. It works, thanks a ton!
From: Olly

2) Meh… there is always a chance but i very much doubt we will ever get a major update to Lape again, so no classes. :(

Can't we update it ourselves? I wouldn't mind looking into adding classes. I could do it if I get enough time.

Olly

2014-11-10 17:12:26

From: akarigar
That's sexy. It works, thanks a ton!

Can't we update it ourselves? I wouldn't mind looking into adding classes. I could do it if I get enough time.


Of course, Everything is open source… :)

Our copy https://github.com/SRL/Lape
Official: https://code.google.com/p/la-pe/source/list

Goodluck!

e: Hopefully soon you will be able to do VariantInvoke('Bankscreen.clickButton', [0, True]); if my commit goes though, only bad thing is that its limited to variants so if any parameters or results cant be casted to a variant you won't have it.

KeepBotting

2014-11-10 17:35:14

From: akarigar
Hey guys, I was wondering if someone could point me in the right direction here.



I see what you did there.

Brandon

2014-11-10 17:53:09


type
FooObj = record
i: Integer;
end;

procedure FooObj.open(x: Integer);
begin
writeln('called: ', x + self.i);
end;


procedure callClassFunc(f: function(x: Integer): Boolean; obj: pointer; v: Integer);
type fptr = function(self_ptr: pointer; x: Integer): Boolean;
begin
fptr(@f)(obj, v);
end;


procedure callClassFunc2(f: function(x: Integer): Boolean of Object; v: Integer);
begin
f(v);
end;

var
p: FooObj;
begin
p.i := 21;
callClassFunc(@p.Open, @p, 10);
callClassFunc(@FooObj.Open, @p, 11);
callClassFunc2(@p.Open, 12);
end.


called: 31
called: 32
called: 33
Successfully executed.


For Olly: https://villavu.com/forum/showthread.php?t=110548&p=1312725#post1312725 VariantInvoke on a PtrUInt cast.. is the workaround.

akarigar

2014-11-10 18:01:02

From: Olly
Of course, Everything is open source… :)

Our copy https://github.com/SRL/Lape
Official: https://code.google.com/p/la-pe/source/list

Goodluck!

e: Hopefully soon you will be able to do VariantInvoke('Bankscreen.clickButton', [0, True]); if my commit goes though, only bad thing is that its limited to variants so if any parameters or results cant be casted to a variant you won't have it.


Alright, cool. It would require a lot of work, so when I get a few weeks to dedicate, I'll definitely give it a shot. Might PM you for some info when I get started on it.

Nice, I'm looking forward to VariantInvoke.

From: KeepBotting
I see what you did there.

;)

From: Brandon

type
FooObj = record
i: Integer;
end;

procedure FooObj.open(x: Integer);
begin
writeln('called: ', x + self.i);
end;


procedure callClassFunc(f: function(x: Integer): Boolean; obj: pointer; v: Integer);
type fptr = function(self_ptr: pointer; x: Integer): Boolean;
begin
fptr(@f)(obj, v);
end;


procedure callClassFunc2(f: function(x: Integer): Boolean of Object; v: Integer);
begin
f(v);
end;

var
p: FooObj;
begin
p.i := 21;
callClassFunc(@p.Open, @p, 10);
callClassFunc(@FooObj.Open, @p, 11);
callClassFunc2(@p.Open, 12);
end.


called: 31
called: 32
called: 33
Successfully executed.

Thanks for this, learned something new in Lape :)