Mapping unmanaged data to a managed structure in .NET

.net, c#, pinvoke, unmanaged, winapi

Solution

If you really want to change the order of your member variables, you can do it by using the `FieldOffsetAttribute`. Just makes it a little bit less readable.

You'll also need to set your `StructLayout` to `LayoutKind.Explicit` to indicate you are setting the offsets yourself.

Example:

[StructLayout(LayoutKind.Explicit)]
public struct RECT
{
    [FieldOffset(4)]  public int top;
    [FieldOffset(8)]  public int right;
    [FieldOffset(12)] public int bottom;
    [FieldOffset(0)]  public int left;
}

Problem

I have spent many hours working with unmanaged code, and platform invoke in .NET. The code below illustrates something that is puzzling me regarding how unmanaged data is mapped to a managed object in .NET. For this example I am going to use the RECT structure: C++ RECT implementation (unmanaged Win32 API) ``` typedef struct _RECT { LONG left; LONG top; LONG right; LONG bottom; } RECT, *PRECT; ``` C# RECT implementation (managed .NET/C#) ``` [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left, top, right, bottom; } ``` Okay, so my C# equivalent should work, right? I mean, all of the variables are in the same order as the C++ struct, and it's using the same variable names. My assumption of `LayoutKind.Sequential` means that the unmanaged data is mapped to the managed object in the same sequence it appears in the C++ structure. i.e. the data will be mapped, starting with left, then top, then right, then bottom. On this basis I should be able to modify my C# structure... C# RECT implementation (a bit cleaner) ``` [StructLayout(LayoutKind.Sequential)] public struct Rect //I've started by giving it a .NET compliant name { private int _left, _top, _right, _bottom; // variables are no longer directly accessible. /* I can now access the coordinates via properties */ public Int32 Left { get { return _left; } set { this._left = value; } } public Int32 Top { get { return _top; } set { this._top = value; } } public Int32 Right { get { return _right; } set { this._right = value; } } public Int32 Bottom { get { return _bottom; } set { this._bottom = value; } } } ``` So what happens if the variables are declared in the wrong order? Presumably this screws up the coordinates because they will no longer be mapped to the correct thing? ``` public struct RECT { public int top, right, bottom, left; } ``` At a guess, this would map like so: top = left right = top bottom = right left = bottom So my question is simply, Am I correct in my assumption that, I can modify the managed structure in terms of the access specifier of each variable, and even the variable name, but I cannot alter the order of the variables?

Original source