Get Byte ptr to type method ?

BlitzMax Forums/BlitzMax Programming/Get Byte ptr to type method ?

skn3(Posted 2004) [#1]
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 ?


FlameDuck(Posted 2004) [#2]
Are you thinking about Function Ponters? Or do you need it for something else?


skn3(Posted 2004) [#3]
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.


marksibly(Posted 2004) [#4]
It's not doable.


skn3(Posted 2004) [#5]
Thanks :)


N(Posted 2004) [#6]
Just for the sake of asking, why isn't it doable?

Not saying it's in any way limiting, just curious.


Bot Builder(Posted 2004) [#7]
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.


marksibly(Posted 2004) [#8]

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.


N(Posted 2004) [#9]
Thanks for the anwer- makes plenty of sense now.


ImaginaryHuman(Posted 2005) [#10]
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?


ImaginaryHuman(Posted 2005) [#11]
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?


Robert(Posted 2005) [#12]
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?


ImaginaryHuman(Posted 2005) [#13]
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!


Floyd(Posted 2005) [#14]
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



ImaginaryHuman(Posted 2005) [#15]
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.


Bot Builder(Posted 2005) [#16]
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.


ImaginaryHuman(Posted 2005) [#17]
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?


Bot Builder(Posted 2005) [#18]
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.


ImaginaryHuman(Posted 2005) [#19]
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.