Cast object to int Handle and back??
August 28, 2017 at 4:17 pm #10073
Is it possible to convert an object to integer and back?
The following code creates a ‘Memory access violation’:1234567891011121314151617181920Class TestField Name:StringEndFunction ToHandle:Int(obj:Object)Local iPtr:= Cast<int Ptr>(Varptr obj)return Int(iPtr)EndFunction FromHandle<T>:T(handle:Int)Return Cast<T Ptr>(Cast<int Ptr>(handle))EndLocal test:= New Testtest.Name = "IntHandleTest"Local handle:= ToHandle(test)Local obj:= FromHandle<Test>(handle)Print obj.Name
Another question: How do I recieve default parameter values from a function DeclInfo?August 29, 2017 at 3:53 am #10084
This isn’t really recommended as the GC is not aware of ‘handles’ so may reclaim the object at any time if there is not a variable somewhere containing the object while you’re using the handle. Also, an Int wont be big enough to hold an object address on all targets. You’re better off using a Ptr type which will always be exactly the right size.
But here’s a way to do it anyway. This relies on the fact that, while you can’t currently cast an object to a Void Ptr or similar (perhaps one day), you *can* use Varptr with object variables.1234567891011121314151617181920212223242526272829303132333435363738394041424344#Import "<std>"Using std..Function ObjectToPointer:Void Ptr( obj:Object )Return obj ? Cast<Void Ptr Ptr>( Varptr obj ) Else NullEndFunction PointerToObject:Object( vptr:Void Ptr )Return vptr ? Cast<Object Ptr>( Varptr vptr ) Else NullEndClass CField x:Int=0Method Test:String()x+=1return "x="+xEndEndGlobal c:CFunction Main()c=New CLocal p:=ObjectToPointer( c )Print "Address of object:$"+Hex( Cast<ULong>( p ) )Print "Testing Object:"+c.Test()Local c2:=Cast<C>( PointerToObject( p ) )Local p2:=ObjectToPointer( c2 )Print "Address of object:$"+Hex( Cast<ULong>( p2 ) )Print "Testing Object:"+c2.Test()End
Note that the ‘New C’ is assigned to a global, not a local. This ensures that the new object is ‘kept alive’ and not prematurely GC’d while you’re hacking around with its ‘handle’.
I use a similar technique in mojo3d-physics to set the bullet rigidbody ‘user data’ ptr to the Entity the rigibody is attached to. This allows me to quickly find the Entity involved when bullet reports a collision between rigibodies or something.
It’s safe because the Entity is being kept alive by being in an internal global Scene stack. Destroying an Entity both removes it from its stack (allowing it to be GC’d) and sets its rigidbody ‘user data’ ptr to null.
This is pretty much the most efficient way to do this sort of ‘binding’ of monkey2 objects with external objects that provide a ‘user data’ ptr or similar, so I think it’s worth people knowing about, but it *is* a bit dangerous so be careful!
But in general, most games will store Entities in a global stack or list somewhere, in which case it’s generally safe to use ObjectToPointer() on them – until, that is, they are removed from their global stack/list, usually via explicit Destroy() call or similar. After this, the Entity becomes ‘usafe’ as it may be collected by GC at any time, so any pointers to it should be considered invalid. But you don’t generally need the pointer any more anyway as the Entity has been destroyed!August 29, 2017 at 4:00 am #10085
Another question: How do I recieve default parameter values from a function DeclInfo?
You can’t, DeclInfo doesn’t know about default parameters.September 5, 2017 at 11:00 am #10282
Thank you very much!
You must be logged in to reply to this topic.