开发者

Conversion from void* to object in C#

开发者 https://www.devze.com 2023-01-05 15:02 出处:网络
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

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 = CastPoi开发者_如何学PythonnterToObject(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).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号