Small addition to BRL Reflection: Get Function ptr
BlitzMax Forums/BlitzMax Module Tweaks/Small addition to BRL Reflection: Get Function ptr| 
 | ||
| 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. | 
| 
 | ||
| Can it be used to get method pointers? | 
| 
 | ||
| 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. | 
| 
 | ||
| It would be cool if the reflection module would support full function and type function support. | 
| 
 | ||
| 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: | 
| 
 | ||
| @grable bbGCRetain and bbGCRelease have been deprecated, I believe. | 
| 
 | ||
|  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. | 
| 
 | ||
|  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? | 
| 
 | ||
|  Yeah, i havent taken the plunge to 1.32 yet ;) but isnt the old GC still in use when not using threading?  Yes. | 
| 
 | ||
| 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 . |