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?