In a C# project, I need to pass object parameters by putting references in a structure. i.e. I have a structure passed to a dispatcher
struct SOMESTRUCT
{
public int lpObject;
}
Where lpObject holds a pointer to a custom object like
class SomeClass
{
private string foo;
}
And the SOMESTRUCT structure is passed from method to method to finally reach my code. I cannot modify the execution flow nor the strange SOMSTRUCT system, so I guessed the only solution was to cast my object to a pointer like this :
var myObject = new SomeClass();
GCHandle GC = GCHandle.Alloc(myObject, GCHandleType.Pinned);
int myRef = GC.AddrOfPinnedObject().ToInt32();
GC.Free();
SOMESTRUCT struct;
struct.lpObject = myRef;
someMethod(struct);
However, I can't figure out how to retrieve the myObject members from the lpObject fields. Something like this:
SomeClass myObject = CastPointerToObject(struct.myRef) as SomeClass;
Is there a way to do it, or is it impossible ? How can I tell the garbage collector to handle the object ? Should I create a new Garbage-collected object and copy the data field by field ?
TYIA,
no No NO NO NO!!!
This
struct SOMESTRUCT
{
public SomeClass object_ref;
}
Is the correct way to store a reference in a struct.
The code you have written, and the accepted answer, are 100% broken.
The address returned by GC.AddrOfPinnedObject(GCHandle)
is only valid while the GCHandle
is intact. You must not call GCHandle.Free
, and you must not let the GCHandle
get collected. In your code, the address is already meaningless by the time you store it.
But you should just let .NET take care of managing the pointer during garbage collection, by using a variable of reference type. Then you don't need to jump through hoops. The only reason to take the address of a managed object is when passing it to an existing native DLL function that will save the pointer after it returns. For example, it's necessary with OpenGL buffer arrays. It is NOT necessary, ever, when calling other C# methods.
If SOMESTRUCT is actually a native data type used by some DLL function you haven't mentioned, then you'll need to make sure to keep the GCHandle
alive. Only as long as the GCHandle
exists will the pointer you got remain valid.
Do you mean you want to cast the returned pointer back to a struct?
Similar to:
lvHitTestInfo = (LVHITTESTINFO)Marshal.PtrToStructure(lP, typeof(LVHITTESTINFO));
Where lvHitTestInfo is a structure and lp a pointer.
Or i didn't understand your question properly. Maybe you can explain more (more complete code sample).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With