Can I store a list of method callback pointers?

BlitzMax Forums/BlitzMax Programming/Can I store a list of method callback pointers?

SofaKng(Posted 2007) [#1]
I'd like to store a list of method callback pointers and then iterate through them (at a later time) and call each one of them.

Is this possible?

Thanks...

- John

===> UPDATE <===

I figured it out... I really didn't think BlitzMax was this powerful!

In case anybody is wondering, here is how I did it:

  ' Delcare an array of callbacks functions...
  '
  ' Each callback function must be in format:
  '    Function xxxx : Int (Path : String)

  Field Funcs : Int (Path : String) [20]

  ' You can then access the array like any other array...

  ' Assuming Funcs[0] is assigned, then this will work:
  Funcs[0]("This is my path parameter.")



SofaKng(Posted 2007) [#2]
The only thing I can't figure out is how to define a callback that takes no parameter and has no return type.

Is this possible?

I can just give the callback definition a return type of Int and then have the function not return anything, but this is sloppy...


Gabriel(Posted 2007) [#3]
What's wrong with just..

Field Func()


.. ?


SofaKng(Posted 2007) [#4]
Nice, thanks!

I was trying:
  Field Funcs : () [20]


However, your code works just fine...

  Field Funcs() [20]


I've read that actually all functions/methods default to an Int return type so I guess that's what is happening in the above examples. That seems a little bit sloppy to me, but no big deal!

Once again, I really like the power of BlitzMax!


ImaginaryHuman(Posted 2007) [#5]
The () defines it as a function type, like you would if you used `:int` or ':float', you just leave out the colon.

Funcs() is a function pointer

Function pointers are really cool. You can re-wire your app at runtime with them.


Dreamora(Posted 2007) [#6]
Stupid q: where is here a solution for method pointers?

Function pointers are no problem, but method pointers simply are impossible as they do not exist ... little missleading thread title.


ImaginaryHuman(Posted 2007) [#7]
Here is my code idea from a previous thread about method pointers, which you might be happy to use for this purpose:

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=MyType.ActuallyDoSomethingElse
Instance.PrintIt(15)

From here: http://www.blitzbasic.com/Community/posts.php?topic=65492#731769
"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?"

Does that work for you?


SofaKng(Posted 2007) [#8]
@Dreamore: Good point. In fact, I completely overlooked this and I actually DO want *METHOD* pointers and not function pointers. In my testing I was using function pointers which is why it worked.

Is there any way to store method pointers? If I understand correctly they are actually two pointers (one pointer to the object and another to the method). A normal function pointer is simply one pointer.

Another question...

Can I store function pointers (and/or method pointers) in anything besides an array? (eg. TList, TMap, etc...)

Also, I'm a bit confused on multi-dimensional arrays in BlitzMax.

If I declare my array like this:
Local Arr : Int[800, 600]


Wouldn't Arr[799, 599] be the last element? I'm confused because BlitzMax allows you do this:

  Arr[1000, 1000] = "Hello"


...without throwing an error!

Finally... (last question!) Can you resize multi-dimensional arrays? Is this slow to do? (does it copy the entire array while copying it?)

Thanks again for all of your help!!


ImaginaryHuman(Posted 2007) [#9]
See my post just above your message - you posted at the same time as me so maybe you didn't see it.

You can store function pointers wherever you like, in an array, a list, a type field, a local, a global, whatever.

I am not so sure on the array question. Did you compile with debug on, because I'd think you'd get an array bounds error.

Not sure about resizing multidimensional - look at `slices` in the documentation.


grable(Posted 2007) [#10]
If I declare my array like this:

Local Arr : Int[800, 600]

Wouldn't Arr[799, 599] be the last element? I'm confused because BlitzMax allows you do this:

Arr[1000, 1000] = "Hello"

...without throwing an error!


For speed reasons (i guess) indices are not checked at runtime in release mode.
But in debug mode they ARE checked.


Dreamora(Posted 2007) [#11]
Its more because the array debug part of the module is only imported in debug but not in release. If you need to test in in realtime because you didn't spend time on debugging state, then using Try - Catch - End Try should throw an exception in this case.


skidracer(Posted 2007) [#12]
Memory Access Violations cause exceptions?

I was under the impression writing outside arrays in release mode would obliterate all your other variables and then perhaps cause a page fault which I'm pretty sure isn't going to be much help to anyone.


Dreamora(Posted 2007) [#13]
Erm in what way is using a Blitz Object a MAV thing if it is initialized?
Accessing a NULL object is a MAV, I agree.

Accessing a :Array with a not existing index thought is something which most languages see as reason to fire an Array Index out of Bound exception.

But I agree that it normally shouldn't happen. Correct code with ASSERT for preconditions, postconditions and invariants actually make sure that such a thing NEVER can happen at all.