internal void ReadStruct(NSData data)
        {
            IntPtr buffer = data.Bytes;

            connectionParams = (MidiThruConnectionParamsStruct)Marshal.PtrToStructure(buffer, typeof(MidiThruConnectionParamsStruct));

            // Put ourselves at the end of the static struct in case we need to fetch the dynamic part of the struct
            IntPtr bufferEnd    = IntPtr.Add(buffer, Marshal.SizeOf(typeof(MidiThruConnectionParamsStruct)));
            var    controlsSize = Marshal.SizeOf(typeof(MidiControlTransform));

            if (connectionParams.NumControlTransforms == 0)
            {
                Controls = null;
            }
            else
            {
                Controls = new MidiControlTransform[connectionParams.NumControlTransforms];
                unsafe {                 // Lets use memcpy to avoid a for loop
                    fixed(MidiControlTransform *arrAddr = &Controls[0])
                    Runtime.memcpy((IntPtr)arrAddr, bufferEnd, controlsSize * connectionParams.NumControlTransforms);
                }
            }

            if (connectionParams.NumMaps == 0)
            {
                Maps = null;
            }
            else
            {
                Maps      = new MidiValueMap [connectionParams.NumMaps];
                bufferEnd = IntPtr.Add(bufferEnd, controlsSize * connectionParams.NumControlTransforms);
                unsafe {                 // Lets use memcpy to avoid a for loop
                    for (int i = 0; i < connectionParams.NumMaps; i++)
                    {
                        Maps [i].Value = new byte [128];

                        fixed(byte *arrAddr = &Maps[i].Value[0])
                        Runtime.memcpy((IntPtr)arrAddr, bufferEnd, 128);
                    }
                }
            }
        }
 extern static void MIDIThruConnectionParamsInitialize(out MidiThruConnectionParamsStruct inConnectionParams);