Welcome to Ars-Informatica  


If you want to build a ship don't herd people together to collect wood and don't assign them tasks and work, but rather teach them to long for the endless immensity of the sea. (Antoine-Marie-Roger de Saint-Exupéry)

Pinning structures in .NET

Dealing with embedded systems one of the most powerfull operations that C(C++) users are used to is the mapping of a memory area to a particular structure (struct). This simple operation that involves memory layout is lacking in .NET due to the existence of the garbage collector. To face this problem two solutions are available:

  • A dirty one: using the unsafe keyword along with the fixed keyword to pin the object in the garbage collector memory.
  • A clean one: using GCHandle and Marshal.

In this brief article this second solution is explained. Consider you have a C structure:

        typedef struct 
            int an_integer; 
            short a_short; 
            char a_string[16]; 
        } mystruct;

In C# (by using properties) you'd write:

        [StructLayout(LayoutKind.Sequential, Pack = 1)] 
        public struct MYSTRUCT 
            public Int32 an_integer; 
            public Int16 a_short; 
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] 
            public string a_string; 

Now to convert a byte[] (called bytes) to MYSTRUCT use the following code:

        GCHandle pinnedBytes = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
        MYSTRUCT mystruct = (MYSTRUCT)Marshal.PtrToStructure( 
            pinnedBytes.AddrOfPinnedObject(), typeof(MYSTRUCT)

To convert back MYSTRUCT to byte[] write:

        int size = Marshal.SizeOf(mystruct); 
        byte[] bytes = new byte[size]; 
        GCHandle pinnedBytes = GCHandle.Alloc(bytes, GCHandleType.Pinned);
        Marshal.StructureToPtr(mystruct, pinnedBytes.AddrOfPinnedObject(), true );