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. |