I try parse a byte array to struct but it doesnt work with Sequential. The values are wrong in the Sequential struct but it work correct with Explicit struct? I need sequential the byte array have no fix length. The DwLength field is the size of Data field.
Values
Test Code
var bytes = new byte[] { 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x3B, 0x8F, 0x80, 0x01, 0x80, 0x4F, 0x0C, 0xA0, 0x00, 0x00, 0x03, 0x06, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x68 };
var result1 = GetStruct<RdrToPcDataBlock1>(bytes);
var result2 = GetStruct<RdrToPcDataBlock2>(bytes);
struct RdrToPcDataBlock Sequential
[StructLayout(LayoutKind.Sequential)]
public struct RdrToPcDataBlock1
{
public byte MessageType;
public int DwLength;
public byte Slot;
public byte Seq;
public byte Status;
public byte Error;
public byte ChainParameter;
[MarshalAs(UnmanagedType.ByValArray)]
public byte[] Data;
}
struct RdrToPcDataBlock Explicit
[StructLayout(LayoutKind.Explicit)]
public struct RdrToPcDataBlock2
{
[FieldOffset(0)]
public byte MessageType;
[FieldOffset(1)]
public int DwLength;
[FieldOffset(5)]
public byte Slot;
[FieldOffset(6)]
public byte Seq;
[FieldOffset(7)]
public byte Status;
[FieldOffset(8)]
public byte Error;
[FieldOffset(9)]
public byte ChainParameter;
[FieldOffset(10)]
public byte Data;
}
GetStruct
public T GetStruct<T>(byte[] bytes)
{
try
{
var handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var item = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return item;
}
catch
{
return default(T);
}
}
When you do [StructLayout(LayoutKind.Sequential)]
that is the same as doing [StructLayout(LayoutKind.Sequential, Pack=0)]
which will use the default packing for the bitness of the process (4 for 32 bit and 8 for 64 bit). To get the behavior your want you need to explicitly say you don't want any padding by setting [StructLayout(LayoutKind.Sequential, Pack=1)]
UPDATE: You still are going to run in to problems with your variable length byte array. See the comment by Jean-Bernard Pellerin
You will have to use a custom marshaller. Otherwise you can't deal with variable length arrays. Here's an example: https://stackoverflow.com/a/38884095/103959
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With