User Tools

Site Tools


gchandle

GCHandle: cast an object to a number

When working with callback functions and the Windows API, sometimes it is important to map an object to a numeric variable. In VO, often the object was casted to an int variable. This was possible since in VO and Win32 a pointer has the same width as an int, but it could lead to problems if the object was moved by the garbage collector. Therefore this is dangerous and could lead to problems if not used correctly. In X#, this is not more possible, as a pointer can also be 64 bit wide (when the program runs in x64 mode), cannot be casted to an int. Please see below for a thread on the X# forum.

Fortunately in the .NET Framework there is another possibility: the System.Runtime.InteropServices.GCHandle structure: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.gchandle

Basically, you can get a handle from an object and lock it in memory so the garbage collector will not move it around:

local oHandle as GCHandle
oHandle := GCHandle.Alloc( oMyObject )

and then get a pointer to it:

local ptrObject as IntPtr
ptrObject := GCHandle.ToIntPtr( oHandle )

To return then the object from the IntPtr (that is 32 bit wide in x86 mode, and 64 bit in x64 mode), you can use this code:

local oHandle as GCHandle
local oObject as MyObject
oHandle := GCHandle.FromIntPtr( ptrObject )
oObject := (MyObject) GCHandle.Target

And since you have locked this object in memory, it is very important to release it also with

oHandle:Free()

There is also a sample by Microsoft: https://msdn.microsoft.com/en-us/library/44ey4b32(v=vs.110).aspx

For explanations by the development team, please see: https://www.xsharp.info/forum/public-product/832-2-0-0-2-cannot-cast-type-int-to-object

gchandle.txt · Last modified: 2018/09/07 06:23 by wolfgangriedmann