views:

1263

answers:

2

I'm having some trouble with this code:

//Creating a new ImageElement Struct
ImageElement oElement = new UM0516.ImageElement();
//Create a pointer and allocate enough room for the struct type
IntPtr pElement = Marshal.AllocHGlobal(Marshal.SizeOf(new UM0516.ImageElement()));
//Copy the contents of the struct into the allocated memory space
Marshal.StructureToPtr(oElement, pElement, true);
//Function that takes a file pointed to by handle, and does some sweet sweet things
//And returns a loaded struct pointed to by pElement
FILES_GetImageElement(handle, el, out pElement);

Here is where I get confused: I'll step through the code, and after I call that last function (which should change some bits in memory pointed to by pElement), I see a change to oElement!? I thought the Marshal.StructureToPtr "copies" data from a managed struct to memory. So are the two locations actually the same? Managed struct oElement and allocated memory pointed to by pElement?

A: 

I think you probably don't need to manually marshal the structure to a pointer. As long as the managed version of the structure matches the layout of the unmanaged struct then let the interop marshaler take care of marshaling.

You should be able to get rid of pElement entirely and pass oElement as either a ref parameter (if you care about what's in it on the way in) or an out parameter.

Arnshea
Afaik this requires unsafe pointers and the *fixed* statement in C# (such as unsafe int * ) to avoid that the garbage collector does not move the memory around (i.e. the memomry must be pinned).
0xA3
Or using System.Runtime.InteropServices.GCHandle should do it (as the documentation to Marshal.StructureToPtr says).
0xA3
+1  A: 

This article explains it in detail:

Formatted blittable classes have fixed layout (formatted) and common data representation in both managed and unmanaged memory. When these types require marshaling, a pointer to the object in the heap is passed to the callee directly. The callee can change the contents of the memory location being referenced by the pointer.

0xA3