Function Pointers: What are They and Why You Should Care
Foreword:
Why hello and welcome, everyone! This tutorial focuses on a concept that I have only rarely seen around here. Function Pointers are the idea of treating a procedure (or function) as a variable. That's a difficult concept for most to wrap their minds around, so I will dedicate a section just to try and explain and help you guys out.
I have seen a very rare few people implement function pointers, and only in cases where "procs" were already defined and the scripter simply redirected them. And even worse, I have never seen any sort of tutorial on them!
Table of Contents:
- What Is a Function Pointer?
- When are they used now?
- How you can use them to Improve Script Efficiency!
- FAQ
What Is a Function Pointer?
A function pointer is simply another variable type that represents a place in script memory instead of a dedicated value. So you can treat this "variable" as a dedicated function to solve your problems.
Why should you care that you can do this instead of just calling the function you want to call? Occasionally, you don't know at compile time what function you want to call. "Well that's just ridiculous, Kevin. I always know what procedure I want to call and when." Wrong (or maybe you weren't thinking that, and in that case I'm sorry), and you will see why you're wrong next.
When are they used now?
My example will be the only case I have ever seen anyone else knowingly use a Function Pointer:
Simba Code:
SRL_Procs[srl_OnRSUpdate]:= @SixHourFix;
Maybe you haven't seen that situation before, so I'll explain it for you. That right there is how our six hour fix currently works by default. SRLProcs[srl_OnRSUpdate] is a function pointer that will call whatever function it is pointing at when the six hour fix is necessary to be run. Using that you can redirect it to point at your own Six Hour Fix procedure (with a different name) to run your own code. The main thing to note with a function pointer is that when you are pointing your variable at a procedure, you must add an at symbol '@' prior to the name of the procedure you plan on pointing at. So let's give a very quick example based on the previous:
Simba Code:
procedure RestartSmart;
begin
//Your custom smart restart code
end;
begin
SRL_Procs[srl_OnRSUpdate]:= @RestartSmart;
//Your normal code
end.
Well that's a fairly simple example, but it should give the basic syntax of existing scenarios for you. This still seems fairly limited though to most people, I mean outside of that one case, why should you care? Because it can improve the runtime of your script and cut down on 'if' and 'case' statements dramatically!
How you can use them to Improve Script Efficiency!
Ok, now I'm obviously just messing with you. I mean, how could this stupid and rare scenario ever matter to you? Because it can remove the necessity of 'if' or 'case' statements when your script allows multiple scenarios. Let's look at the idea of a basic AIO mining script. When you see one right now, the code is sorted roughly like this:
Simba Code:
const
MineWhere = 'Lumbridge'; //Pick Lumbridge, Falador, or AlKharid
procedure MineLumbridge;
begin
//mine a rock at lumbridge
end;
procedure MineAlKharid;
begin
//mine a rock at Al Kharid
end;
procedure MineFalador;
begin
//mine a rock at Falador
end;
procedure BankLumbridge;
begin
//bank your ores in Lumbridge
end;
procedure BankAlKharid;
begin
//bank your ores in Al Kharid
end;
procedure BankFalador;
begin
//bank your ores in Falador
end;
begin
SetUpSRL;
DeclarePlayers;
LoginPlayer;
repeat
repeat
case MineWhere of
'Lumbridge':MineLumbridge;
'AlKharid':MineAlKharid;
'Falador':MineFalador;
end;
FindNormalRandoms;
if(InvFull)then
begin
case MineWhere of
'Lumbridge':BankLumbridge;
'AlKharid':BankAlKharid;
'Falador':BankFalador;
end;
end;
until(not loggedIn);
until(not logInPlayer);
end.
Well, that is one possible setup without function pointers, there could be entire methods that handle the whole looping scenario for each city that ends up wasting a lot of re-usable code space. So how could we possibly enchance this with a Function Pointer? Easily, like this:
Simba Code:
const
MineWhere = 'Lumbridge'; //Pick Lumbridge, Falador, or AlKharid
var
Mine, Bank: procedure();
procedure MineLumbridge;//procedures were all declared like normal
begin
//mine a rock at lumbridge
end;
procedure MineAlKharid;
begin
//mine a rock at Al Kharid
end;
procedure MineFalador;
begin
//mine a rock at Falador
end;
procedure BankLumbridge;
begin
//bank your ores in Lumbridge
end;
procedure BankAlKharid;
begin
//bank your ores in Al Kharid
end;
procedure BankFalador;
begin
//bank your ores in Falador
end;
begin
SetUpSRL;
DeclarePlayers;
LoginPlayer;
case MineWhere of
'Lumbridge':begin
Mine:= @MineLumbridge;//Setting the variable is where you see that '@'
Bank:= @BankLumbridge;
end;
'AlKharid':begin
Mine:= @MineAlKharid;
Bank:= @BankAlKharid;
end;
'Falador':begin
Mine:= @MineFalador;
Bank:= @BankFalador;
end;
end;
repeat
repeat
Mine();//Finally when you call it, you must add the parenthesis even if you aren't passing it any variables! It's a syntax requirement.
FindNormalRandoms;
if(InvFull)then
Bank();
until(not loggedIn);
until(not logInPlayer);
end.
Not only was this code way smaller, but now we got rid of those case statements - thus improving the scripts efficiency! I hope this has helped you and I hope to see these used more often in the future!
For a far more realistic and useful example, feel free to look here:
http://villavu.com/forum/showthread.php?t=104249
FAQ:
Ask me some questions and I'll toss them up here.