Get Byte ptr to type method ?
BlitzMax Forums/BlitzMax Programming/Get Byte ptr to type method ?
| ||
Yet another question from me, but, can anyone tell me how, if possible at all, to get a byte ptr pointing to a type method.Type test Method func() End Method End Type Global t:test = New test Global p:Byte Ptr = Byte Ptr(t.func) This doesn't work. Any ideas ? |
| ||
Are you thinking about Function Ponters? Or do you need it for something else? |
| ||
I was thinking about a method pointer, but using it in a similar way to a function pointer. If its not doable, I'll just use a function for it instead. |
| ||
It's not doable. |
| ||
Thanks :) |
| ||
Just for the sake of asking, why isn't it doable? Not saying it's in any way limiting, just curious. |
| ||
Well, from my experience in C code, as you might expect, BlitzMax calls methods by passing the object as the first parameter. So, IMHO you should be able to do it if you pass the instance of the object you want to use as the first parameter. However, there isn't actually to much use in doing this as if you know to pass a specific type as a parameter, then you might as well just call the type's method and not have a pointer! So basically, method pointers are pointless. I admit, a pointer to a method of a specific instance could be handy, but as mark says, internally impossible without some interesting pointer format system. |
| ||
Just for the sake of asking, why isn't it doable? Well, revise that - it's doable, just a little tricky. Ideally, you just want to be able to go: Local SomeFun(x)=obj.SomeMethod SomeFun( 10 ) However, to implement this, 'SomeFun' needs to store 64 bits worth of info: a pointer to the 'obj', and a pointer to the 'SomeMethod', as 'SomeMethod' will likely need 'obj' (it's 'Self') - ie: the SomeFun(10) call is really obj.SomeFun(10). This of course totally messes up 'normal' function calls, so you get into the territory of having to invent a new construct for 'method pointers'. These are commonly called 'delegates' in other languages. Personally, I'd much rather see function pointers and delegates unified, but am yet to think of a way to do it 'nicely'. Its one of many things I will likely take another look at one day. |
| ||
Thanks for the anwer- makes plenty of sense now. |
| ||
Although all of this is understandable I'm not totally giving up on it. For me it would be very useful and efficient to be able to call a method by treating it like it's a function. In fact it could mean not having to write a whole load of extra code that wouldn't otherwise be needed. I think the main two things that need to be done are 1) Get the location in memory of the method in a given instance of a type 2) Force this pointer into a function pointer. Part 1 is the only part that I'm not sure about. Part 2 can be achieved easily enough by cludging a static bank onto a function pointer's memory and using PokeInt to write the pointer value - that way it doesn't matter that you're not actually storing a legal `function pointer` in it. As far as getting the pointer for the method in the first place goes, that's the harder part. Mark - perhaps you can let us know how methods are stored. Are they actually stored immediately after the type's Field data? ie we could feasibly find the pointer by finding the pointer to the type instance and adding on the size of the field data, to get to the method? Or maybe these things are all stored more elaborately the scattered? Maybe we could have the method call a function - find the function pointer of the function, then search through memory to find any location where that function pointer exists and identify it as the function call, then backtrack a little to get to the start of the method? (pah, too longwinded, stupid) Any other ideas how we can find the method's pointer? |
| ||
Update. .. I tried the first method - to find the pointer to the last Field in a type and see if maybe the method is stored after that in memory, but it's not. I presume that even though a method looks like it is part of a type instance, it's actually treated like any other function and is probably placed at some other location in the eventual code, and just gets called from each instance of that type ... ie you still don't duplicate the actual code for each instance of the method, but the method can still access the fields? Anyway. How about this - a suggestion for the future. Add 2 commands: PokeVar and PeekVar. Since variable memory is already reserved an extra bank shouldn't need to be defined just to write to a variable's content directly. PokeVar can write any given value into any given variable, and similarly PeekVar returns the value of any given variable. Then this could be coupled with simply supplying maybe a MethodPointer() command to which you pass a handle to a type instance and its method e.g. Local MyMethodPtr()=MethodPointer(obj.mymethod) Then you can go PokeVar myvar,MyMethodPtr - or maybe MethodPointer returns a function pointer in which case myfunction=MethodPointer(obj.mymethod) ?? Something like that. I just can't see a way to get the method pointer because it sort of gets hidden. Suggestions? Is this where I should give up? |
| ||
Personally, I'd much rather see function pointers and delegates unified, but am yet to think of a way to do it 'nicely'. Its one of many things I will likely take another look at one day. The simplest solution would probably be just to treat the method pointer as a normal function, but require an extra object parameter at the start. This means that the pointer could be used easily with multiple objects of a given type. Local someFunction(this:Obj,x)=obj.someMethod() Local temp:Obj=New Obj someFunction(temp,x) If the object parameter was omitted then the compiler would complain that "Pointer to type method [Method Name] requires a [TypeName] as the first parameter." Edit: I can see a problem with this though - what if the programmer tries to do something really stupid like passing Null as the object parameter? |
| ||
Also this would require that method calls always have at least one function parameter. In my situation I need to have zero parameters. I would like to be able to just get the method pointer and use it however I like. Maybe a simple ability to say Local functionpointer()=myinstance.mymethod (except that probably RUNS the method) agh! |
| ||
What's the ultimate goal here? You want different functions in various object instances. This probably means you want to create an object, then assign a function pointer within that object. Something like this: Type FN Field f() End Type Function hello() Print "Hello" End Function Function goodbye() Print "Goodbye" End Function Local h:FN = New FN ; h.f = hello Local g:FN = New FN ; g.f = goodbye Print h.f g.f |
| ||
No, more complicated than that. I need to use an array of function pointers and invoke all of the functions in them using something like For Local index:int=0 to myarraysize-1 myarray[index]() Next Then for every new instance of an object that is created using a custom type, each such object must have its own function or method which has an accessible function pointer. The function pointer will be added to the array of function pointers to be invoked later using that same kind of loop above. Each object instance needs its own function or method because it needs to be able to work on the data in the local Fields in that type instance. If I can get the function pointer to the method I can simply keep the above loop in order to run through the functions. Otherwise I would then have to complicate things and devise a technique to pass/communicate the identity of each object to know which object to operate on. If method pointers were available I could just store the pointer in my function pointer array and invoke it like any other function. Not being able to do this means having to store and retrieve more data to figure out which object to work on. I can't use a function within a type because there is only one instance of the function shared between all instances of the type and to get that function to work specifically on the data in a given instance I would have to pass the object's handle which again is extra overhead and complication, plus the fields that I want it to access would then have to be Globals which totally screws up the point of having multiple objects. The array of function pointers also contains the pointers to various functions which exist already at compile-time, ie pre-defined. I want the pre-defined functions to be called using the exact same simple routine as run-time defined functions (I mean methods). To do otherwise is a lot of extra code and time wasted. So I need to get the method pointer. |
| ||
Erm, no, you don't. You should realize that methods are only actually created once, no matter what. And internally, their first parameter is the type they are modifying, etc.Type Car Field Name$ Method Honk(Loudness#) Print Name$+" honked with a loudness of "+Loudness+" db" EndMethod End Type 'Becomes something like... Type Car Function Honk(o.Car,Loudness#) Print o.Name$+" honked with a loudness of "+Loudness+" db" End Function EndType 'Internally in bmax, probably not a text conversion, an internal representation conversion. If not, at least, in the end, the ASM is like this.You do of course, realize if your scheme was to work every type would have to copy the function's binary data, making type creation tons slower. Many more wasted cycles than your "optimization". And, no, your fields dont have to be global to use them inside functions. |
| ||
Ok. The fields don't have to be global? So you can go: [code] Type mytype a:int Function myfunct() a+1 ' will modify the field a in this type instance? End Function End Type myinstance:mytype=New mytype mypointer()=mytype.myfunct mypointer() [code] and the function can access the a field in each individual type instance? or do I need to do self.a? |
| ||
nope.Field a Function myfunct(o:mytype) o.a:+1 ' will modify the field a in this type instance End Function End Type myinstance:mytype=New mytype Local mypntr(o:mytype) mypntr=mytype.myfunct mypntr(myinstance) Print myinstance.a If you are attempting to use a method as a callback, just make a function that calls the appropriate method/type instance. |
| ||
That's all very well but then you have to pass the object handle to the function. I need to call the function with no parameters. |