HELP: How to write a function pointer to memory?

BlitzMax Forums/BlitzMax Beginners Area/HELP: How to write a function pointer to memory?

Hi folks.

I'm trying to put a function pointer in memory at a given address. The code I'm trying to use to do this is a slight rework of code taken from BlitzMax's PokeInt command. However, it doesn't compile and complains of some problem not being able to convert types. I can't figure out what's wrong with it? Can you help?

myfuncitonsbuf is an address in memory - a byte pointer
offset is an offset in bytes from that base address - an integer
funct1() is previously defined as a function - a function pointer

(Int Ptr(myfunctionsbuf+offset))[0]=Int(funct1) ' Something wrong with this line

I haven't used type casting much so I am a bit confused.

Please don't evaluate whether or not I should be trying to do this, I DO need to do it this way, I just need to know how to make it work. Thanks.

I wondered if maybe it's a problem because the base address of the buffer is a byte pointer and should be an integer? Or maybe I am changing to the wrong types?

Thanks for your help.

Compile Error:Unable to convert from 'Int()' to 'Int'

looks to me like functionpointers can only be saved into something that holds function pointers not into "banks"

I have found a way of doing it, but it isn't very neat. It basically involves placing the function pointer inside a type:


Type TrigFunctionContainer
	Field trigFunction:Double(x:Double) 
End Type

Local containerBank:TBank=CreateBank(SizeOf(TrigFunctionContainer)*3)

Local trigSin:TrigFunctionContainer = New TrigFunctionContainer
Local trigCos:TrigFunctionContainer = New TrigFunctionContainer
Local trigTan:TrigFunctionContainer = New TrigFunctionContainer

trigSin.trigFunction=Sin
trigCos.trigFunction=Cos
trigTan.trigFunction=tan

PokeInt(containerBank,0,Int(Varptr(trigSin)))
PokeInt(containerBank,4,Int(Varptr(trigCos)))
PokeInt(containerBank,8,Int(Varptr(trigTan)))

'Test that it is working:

Local func:Double(x:Double)

func=TrigFunctionContainer((Object Ptr(PeekInt(containerBank,0)))[0]).trigFunction

'These statements should print the same result
Print func(120)
Print Sin(120)


I need to explain this line a little:

func=TrigFunctionContainer((Object Ptr(PeekInt(containerBank,0)))[0]).trigFunction


The int is first converted to an object pointer, and then dereferenced using [0] to give an object. Because all custom types are derived from Object, this object can be casted to a TrigFunctionContainer, and we can access the trigFunction field to get the function pointer. Whew!

Hmm, if that works that's certainly a clever effort. I don't know if it's going to be as fast as I was hoping, but at least if it works I can use it for some of the functionality I was hoping for. Thanks!

You know what, it almost looks as though an array of function pointers might end up being faster than this. Hmm. Something like arr[i]=func to store the function pointers and arr[i]() to call them looks like being a lot simpler and faster. I was hoping to access a bank directly and quickly for optimium speed but if it involves a lot of extra stuff it isn't going to be worth it.

I wonder if something like

For i=0 to 9
   myfunctions[i]()   'or myfunctions[i]
Next


would compile down to some kind of optimized form that keeps the array base pointer in a register to be used by each call, instead of re-loading it each time? Oh .. I guess I could say:

Local myfunctions(param:int)[10]
For Local i:int=0 to 9
   myfunctions[i](myparam)
Next i

'or I could even unroll the loop?

Local myfunctions(param:int)[50]
For Local i:int=0 to 49 step 10
   myfunctions[i](myparam)
   myfunctions[i+1](myparam)
   mufunctions[i+2](myparam)
   'etc...+3 +4 +5 +6 +7 +8 +9
next

Would that be faster? I'm just trying to eliminate as much overhead as possible.

Thanks again.

Would it be faster to unroll a loop like that, even though it probably means that +1, +2, +3 etc need to be stored as immediate data in machine code, rather than using a single variable that increments? At least there would be less `loop overhead`.:????

I'm still wishing this whole thing would work with labels so that I can use Goto somehow, removing even the overhead of function calls. Hmm. Gotta rethink this.

You know what, it almost looks as though an array of function pointers might end up being faster than this. Hmm. Something like arr[i]=func to store the function pointers and arr[i]() to call them looks like being a lot simpler and faster. I was hoping to access a bank directly and quickly for optimium speed but if it involves a lot of extra stuff it isn't going to be worth it.


The overhead in calling a function pointer is absolutely minimal compared with any graphics rendering your program might be doing or maths calculations.

Unless I'm doing thousands of function calls. Those little delays add up.