Method pointer?

BlitzMax Forums/BlitzMax Programming/Method pointer?

ziggy(Posted 2006) [#1]
Is there any way to create method pointers? To say, a pointer to a method af a existing instance of a class, like in C#?


ImaginaryHuman(Posted 2006) [#2]
No.

It's been discussed a few times here.


Fetze(Posted 2006) [#3]
Just Create a Function-Pointer that got an object-reference-parameter und call the method.


ziggy(Posted 2006) [#4]
@Fetze: That's exactly what I was trying to avoid. Anyway, thanks Fetze.


Dreamora(Posted 2006) [#5]
"pointer to method" sadly would need delegates or a similar concept. Some here have tried to find ways to "fake" it, but so far we sadly didn't succeed (at least from what I know)


ImaginaryHuman(Posted 2006) [#6]
What do you want to be able to do? Have methods in one type be swapped out for methods in another type? Or do you just want the methods within one instance of a type to be selected?

Since every instance of a type has the same methods, which are taken from the type definition itself, and there is no `custom method code` for each instance of the type, you might as well let functions within the type definition itself be the location of code. In that sense there isn't really any point using Methods at all. But then the only thing you're left with wanting to do is to to be able to access the instance's variables as if they are global within the instance and available across all the function calls within the instance. So then why not have some kind of lookup table of function pointers within the type, which would then be in the instance, which bundles together the `Self` as a parameter passed to the actual functions with code in them that are stored in the type definition ???? ie abstractify the function calls and insert scope changes before the real functions are called? Would that be sufficient to allow you to switch and change which functions are called from each instance, given that each instance now has its own indirect jump table with function pointers local to it?


H&K(Posted 2006) [#7]
I agree with angel, just get a pointer to a Function that takes the object as a parameter, in effect that is the same as a pointer to a method.
As Angel said methods are nearly just function that have been passed self, so I dont realy see why you dont follow what fetze said. Possibly this is one of those situations where we cannot see the point of the question unless you explain why you need it, but ha.


ziggy(Posted 2006) [#8]
@AngelDaniel: that could work in most cases, the fact is that I want a hook to call class methods. I'm making a RAID module, and I need the hook to, once an event is intercepted, to call the appropiate event handler of the appropiate window class, and right now, that is not possible, unless you make a function that recognizes the instance (so all instances have to be stored in a collection) and after that, call a function passing the instance (like self) to that intermediate function that, at the same time, will casts the self parameter to the appropiated class, and then calls the method.... slow, isn't it? Any ideas of how to make this properly?


Dreamora(Posted 2006) [#9]
There is no problem is there.
Because the source holds the needed information.
If you need the window of a specific gadget you could try to use filters and add the window as context on the event fire.

That way you have the window to send to the function pointer.

And from there it is a simple object.method so 1 call.

This logically assumed that your object hierarchy is correct -> all extend from the same base object which has the needed methods declared for the function pointer calling structure.


ziggy(Posted 2006) [#10]
@Dreamora: thw problem is that those events are generated by MaxGUI module, and I can't add this filter information... I've managed to arrange in the way I mentioned up, but I'm afraid it could be easilier done. Of course, all classes extends a base class.


Dreamora(Posted 2006) [#11]
OK I've an easier and faster method:

Assumed you know the window class of each gadget.
Use a TMap, use your gadget reference as key, the window class as value.

Now when the events comes in, you can use the gadget (event source) to get the window class again (don't forget casting to base class of your window classes) and fire the function pointer with that object.

Easy and extremely fast.


ziggy(Posted 2006) [#12]
@Dreamora: Thanks, I think it is a very good idea. I was about to implement a hashtable to do the the same, but using the existing TMAP will be easier. As always your suggestions are very useful.


Dreamora(Posted 2006) [#13]
I'm happy to be able to help (and happy that my minimalistic solutions still works *ggg*)


ImaginaryHuman(Posted 2006) [#14]
My suggested solution isn't exactly the same as what Fetze said. What I was suggesting is that, in terms of how it looks from outside the type, you just call the method you want with the normal parameters you want to pass. From inside the type this is translated into a second function call that includes the Self as an extra parameter.

e.g. something like this (totally untested may be buggy)
Type MyType
   Field FieldA:Int
   Field FieldB:Float
   Field RedirectPrintIt(Value:Int,Who:MyType)

   Method New()
      RedirectPrintIt=ActuallyPrintIt 'default function
   End Function

   Function PrintIt(Value:Int)
      RedirectPrintIt(Value Var,Self)
   End Function

   Function ActuallyPrintIt(What:Int Var,Who:MyType Var)
      Print "Wow "+What
      Print Who.FieldA
      Print Who.FieldB
   End Function

   Function ActuallyDoSomethingElse(What:Int Var,Who:MyType Var)
      Print "Redirected! "+What
      Print Who.FieldA
      Print Who.FieldB
   End Function

End Type

Local Instance:MyType=New MyType
Instance.FieldA=10
Instance.FieldB=12.5
Instance.PrintIt(15)
Instance.RedirectPrintIt=ActuallyDoSomethingElse
Instance.PrintIt(15)


Something like that? You use the Who. in the same way you'd use "Self." - you just can't use `implied` Self like just referring to FieldA=10 within a function. This way you externally only deal with passing the parameters that you really want to deal with, and the Self is handled internally. You have one extra layer of function call going on but it's not a huge overhead and you can `rewire` which method is called as if you had a method pointer.


ziggy(Posted 2006) [#15]
@Angeldaniel: This wouldn't arrange my problem as the functions are called by a hook, and there's no knowledge of the object instance when the function is called, so there's no way to pass the instance as a parameter. I've made an intermediate solution and I've managed to make it work properly, but it is really a pitty that blitzmax doesn't have method pointers (delegates if necesary).


ImaginaryHuman(Posted 2006) [#16]
You are misunderstanding it.

All you need is the function pointer within any given instance. Every instance of the type has its own set of function pointers for all functions, as if they were methods.

Doesn't that solve it?


Koriolis(Posted 2006) [#17]
I believe *you* misunderstood. What he'd like is not actually what is called a method pointer (at least in C++ terminology), but more "delegates". That is, a method pointer packed with the actual instance it is acting on, all in one.


ImaginaryHuman(Posted 2006) [#18]
Like a function with variables defined inside it?


Dreamora(Posted 2006) [#19]
What he needs is a function pointer that is able to operate on a "object hierarchy" (not inheritance) parent object.

And just to mention AD: Your code is elementally bugged!
Self within a function is null even if called on a type instance (only methods have a self as they are per instance, while function are per type!). This is a current compiler bug in 1.22 which will be cleaned with the next major version, so better get a "correct" solution to this fake.


ImaginaryHuman(Posted 2006) [#20]
I never said my code worked, lol It's the idea of it.


Dreamora(Posted 2006) [#21]
the problem is, that currently, your code will work due to this compiler error. Just thought it would be usefull to point out that it is wrong code that just works due to an error deep within BM currently.


ImaginaryHuman(Posted 2006) [#22]
What if you change it to this:

Type MyType
   Field FieldA:Int
   Field FieldB:Float
   Field RedirectPrintIt(Value:Int,Who:MyType)

   Method New()
      RedirectPrintIt=ActuallyPrintIt 'default function
   End Function

   Method PrintIt(Value:Int)
      RedirectPrintIt(Value Var,Self)
   End Function

   Function ActuallyPrintIt(What:Int Var,Who:MyType Var)
      Print "Wow "+What
      Print Who.FieldA
      Print Who.FieldB
   End Function

   Function ActuallyDoSomethingElse(What:Int Var,Who:MyType Var)
      Print "Redirected! "+What
      Print Who.FieldA
      Print Who.FieldB
   End Function

End Type

Local Instance:MyType=New MyType
Instance.FieldA=10
Instance.FieldB=12.5
Instance.PrintIt(15)
Instance.RedirectPrintIt=ActuallyDoSomethingElse
Instance.PrintIt(15)


ie change the PrintIt function to a method?


Dreamora(Posted 2006) [#23]
This should work actually.
Depending on the situation it perhaps might cause some troubles but for general usage definitely a possibility to use and to keep in mind.


ziggy(Posted 2006) [#24]
Yes, it doesn't solve my problem, but it can be something to consider in other situations.


ImaginaryHuman(Posted 2006) [#25]
I'm still trying to understand how your problem differs, Ziggy. You want to have a separate event handler for each window?


ziggy(Posted 2006) [#26]
The event handler is a function (the hook) is a function, outside any class, and events are thrown by MaxGUI gadgets not by the class instances that should handle them. that's the point. I could fix it if the classes would extend the gadget class, but that's not what I want, that's the problem.