Small addition to BRL Reflection: Get Function ptr

BlitzMax Forums/BlitzMax Module Tweaks/Small addition to BRL Reflection: Get Function ptr

BORNtobeNAMELESS(Posted 2009) [#1]
Could be easily build into the Module, but this way the module does not need to be modified:




A Small example how to use it:




I needed this to automaticaly export Types as a Python-Module, maybe someone might find this usefull, too.


Azathoth(Posted 2009) [#2]
Can it be used to get method pointers?


BORNtobeNAMELESS(Posted 2009) [#3]
Method pointers are not possible as Methods allways need an Object to be called. Internaly BRL.Reflection gets a method pointer whenever it invokes a method internaly, but puts the Self-Object on the stack before it calls the method.
See TMethod.Invoke and the private _Call function in BRL.Reflection if you want to know more about it.


Htbaa(Posted 2009) [#4]
It would be cool if the reflection module would support full function and type function support.


grable(Posted 2009) [#5]
Nice addition :)

Can it be used to get method pointers?

Not true method pointers, but it works. (code ripped shamelessly from BRL.Reflection)
Function GetMethodFuncPtr:Byte Ptr( this:Object, name:String)
	If this And name Then	
		Local typ:TTypeId = TTypeId.ForObject(this)
		Local meth:TMethod = typ.FindMethod(name)	
		If meth Then
			If meth._index < 65536 Then Return bbRefMethodPtr( this, meth._index)
			Return Byte Ptr meth._index
		EndIf
	EndIf
	Return Null
EndFunction

Example usage:
Local stream:TStream = WriteFile("test")
Local StreamWriteLine( this:TStream, s:String) = GetMethodFuncPtr( stream, "WriteLine")
StreamWriteLine( stream, "hello")
StreamWriteLine( stream, "world")
stream.Close()

I have an implementation of working method pointers though, using GNU Lightning.. it even plays nicely with the old GC, keeping the object alive until the methodptr is released.
But since the language doesnt support them natively, they have to be created and released manually :(

Its usage looks something like this:
Local stream:TStream = WriteFile("c:\test")
Local StreamWriteLine( s:String) = GetMethodPtr( stream, "WriteLine", 1)
StreamWriteLine("hello")
StreamWriteLine("world")
stream.Close()
ReleaseMethodPtr(StreamWriteLine)

EDIT:
If you want to see how it works, download grb.lightning.mod.x86.rar and run this source:



Brucey(Posted 2009) [#6]
@grable

bbGCRetain and bbGCRelease have been deprecated, I believe.


N(Posted 2009) [#7]
Method pointers are not possible as Methods allways need an Object to be called. Internaly BRL.Reflection gets a method pointer whenever it invokes a method internaly, but puts the Self-Object on the stack before it calls the method.

This is very possible. You can also very easily replace methods.


grable(Posted 2009) [#8]
bbGCRetain and bbGCRelease have been deprecated, I believe.

Yeah, i havent taken the plunge to 1.32 yet ;) but isnt the old GC still in use when not using threading?


N(Posted 2009) [#9]
Yeah, i havent taken the plunge to 1.32 yet ;) but isnt the old GC still in use when not using threading?
Yes.


spacerat(Posted 2009) [#10]
I've been trying to integrate function support into brl.reflection so that it behaves exactly the same as the support for methods, and I've managed to get everything working apart from Invoke(args:Object[]). The code for the whole thing is here http://pastebin.com/f453e43b9 but if you just want to see invoke take a look here.
        Method Invoke:Object(args:Object[] = Null)
                Local q[10], sp:Byte Ptr = q
                sp:+4
                If typeId() = LongTypeId sp:+8
        '       If args <> Null
                        For Local i = 0 Until args.length
                                If Int Ptr(sp)>=Int Ptr(q)+8 Throw "ERROR"
                                sp = _Push(sp, argTypes()[i], args[i])
                        Next
        '       EndIf
                If Int Ptr(sp)>Int Ptr(q)+8 Throw "ERROR"
                       
                Select typeId()
                        Case ByteTypeId, ShortTypeId, IntTypeId
                                Local f:Int(p0, p1, p2, p3, p4, p5, p6, p7) = _fptr
                                Return String.FromInt(f(q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7]))
                        Case LongTypeId
                                Throw "TODO"
                        Case FloatTypeId
                                Local f:Float(p0, p1, p2, p3, p4, p5, p6, p7) = _fptr
                                Return String.FromFloat(f(q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7]))
                        Case DoubleTypeId
                                Local f:Double(p0, p1, p2, p3, p4, p5, p6, p7) = _fptr
                                Return String.FromDouble(f(q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7]))
                        Default
                                Local f:Object(p0, p1, p2, p3, p4, p5, p6, p7) = _fptr
                                Return f(q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7])
                End Select     
        End Method
       
        Field _selfTypeId:TTypeId, _argTypes:TTypeId[]
        Field _fptr:Byte Ptr


Basically, Invoke only seems to work when the function takes no arguments, otherwise the program crashes (no debug information, it just fails). I think if we can fix this, we might have a worthy modification to the official brl.reflection.

EDIT: Fixed it myself. Pastebin for the whole working thing is here http://pastebin.com/f5aa00efa .