How to create and use list of function pointers?

BlitzMax Forums/BlitzMax Beginners Area/How to create and use list of function pointers?

ImaginaryHuman(Posted 2004) [#1]
Hi folks. I need to create and use numerous function pointers and I want to keep them in some kind of list for fast access, but of course it must allow the functions to still be called - and it needs to be quick.

I have three ideas I thought I'd run by you. The first would be to create an array of function pointers somehow and then call each function by accessing the array? The second would be to create a new Type with a single function pointer in it and make an array of that Type, then access the array again to call the functions? Thirdly to use a Bank and store the function pointers as groups of 4 bytes using PokeLong, and read them back and call them using PeekLong? I don't know if any of these methods are possible in BlitzMax. If anyone can shed some light on this it'd be much appreciated.

Here is what I am trying to do, using an array of function pointers .. I don't know if this will even work...

' Trying to use an array of function pointers
Local myfunctions[50](param:int) ' ???
Function doingsomething(p1:int)
   Return p1*10
End Function
Function doingsomething2(p1:int)
   Return p1*20
End Function
For Local f:int=0 to 49
   If (f mod 2)=0
      myfunctions[f]=doingsomething
   Else
      myfuncitons[f]=doingsomething2
   EndIf
Next
For Local f:int=0 to 49
   Print myfunctions[f](f) ' ???
Next


Or using an array of types containing function pointers?...

' Trying to use an array of types containing function pointers
Type myfunct
   field myfunction(param:int)
End Type
Local myfunctions:myfunct[50]
Function doingsomething(p1:int)
   Return p1*10
End Function
Function doingsomething2(p1:int)
   Return p1*20
End Function
For Local f:int=0 to 49
   If (f mod 2)=0
      myfunctions[f].myfunction=doingsomething
   Else
      myfuncitons[f].myfunction=doingsomething2
   EndIf
Next
For Local f:int=0 to 49
   Print myfunctions[f].myfunction(f)
Next


Or using a Bank of function pointers?...

' Trying to use a bank of function pointers
' Maybe I need to be using VarPtr in here somewhere?
Local myfunctions=CreateBank(50*4) ' Not sure on the syntax
Function doingsomething(p1:int)
   Return p1*10
End Function
Function doingsomething2(p1:int)
   Return p1*20
End Function
For Local f:int=0 to 49*4 Step 4
   If (f mod 8)=0
      PokeLong myfunctions+f,doingsomething
   Else
      PokeLong myfuncitons+f,doingsomething2
   EndIf
Next
Local fptr(param:int)
For Local f:int=0 to 49*4 Step 4
   Print PeekLong(myfunctions+f(f)) ' ???
   ' Or should it be: fptr=PeekLong(myfunctions+f)
   '                  Print fptr(f) ' ????
Next


For my purposes I figure the bank method is preferable since I can access it faster and handle my own offsets? I'm guessing the compiler might not like using PeekLong and PokeLong with function pointers?

I've not idea if any of these will work or even compile. Can someone please advise how I can best do this? Please note it needs to be very efficient. Thanks.


skn3(Posted 2004) [#2]
Local pointers()[2]
pointers[0] = one
pointers[1] = three

pointers[0]()
pointers[1]()

Input "> finished, press enter to end"

Function one()
	Print "ONE"
End Function

Function two()
	Print "TWO"
End Function

Function three()
	Print "THREE"
End Function

Function four()
	Print "FOUR"
End Function



ImaginaryHuman(Posted 2004) [#3]
Hmm okay, cool. I will try that out when I get home tonight. Meanwhile, any idea how I can get this working using banks? I need to execute several functions in a row and wish to maintain my own `offset` to the next function pointer in the bank, otherwise I figure time would be wasted getting the base address of the array, finding out the unit size, multiplying it to get to the one I want each time, etc. .. rather than just reading the exact right one at a specific address? That would be preferable for me I'm thinking, rather than use arrays. But thanks though!


skn3(Posted 2004) [#4]
Just do a type of arrays, adding each type instance to a TList


ImaginaryHuman(Posted 2004) [#5]
Ummm ... linked lists also have more math involved to get to the link you want, not as fast?


ImaginaryHuman(Posted 2004) [#6]
Ok, I'm trying to get this to work with a bank of function pointers, but there's something wrong - I can't figure it out. See below.


Rem

Using function pointers to change which function is called dynamically at runtime

With an bank of function pointers

End Rem

Local myfunctions:TBank=CreateBank(10*4)
Local myfunctionsbuf:Byte Ptr
myfunctionsbuf=BankBuf(myfunctions)

Function funct1(param:Int)
	Print "You're in function 1, passed counter parameter="+param
End Function

Function funct2(param:Int)
	Print "You're in function 2, passed counter parameter="+param
End Function

Local counter:Int
Local offset:Int
For counter=0 To 9 Step 2
	offset=counter Shl 2
	(Int Ptr(myfunctionsbuf+offset))[0]=Int(funct1) ' Something wrong with this line
	(Int Ptr(myfunctionsbuf+offset+4))[0]=Int(funct2)
Next

For counter=0 To 9
	offset=counter Shl 2
	(Int Ptr(myfunctionsbuf+offset))[0](counter)
Next

End


There's some difficulty storing the function pointer and retrieving it. Compiler has trouble `converting Int(Int) to Int`. Anyone?