6

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

  • MessageType 128 (Sequential 128)
  • DwLength 20 (Sequential 33554432)
  • Slot 0 (Sequential 0)
  • Seq 0 (Sequential 0)
  • Status 2 (Sequential 59)
  • Error 0 (Sequential 143)
  • ChainParameter 0 (Sequential 128)

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);
    }
}
2
  • "The values are wrong" -- please be more specific. "Wrong", in what way? What result do you get? What result do you expect instead? Please provide a good minimal reproducible example that reliably reproduces the problem, and explain the problem more precisely. Note also that LayoutKind.Sequential is subject to packing rules, so non-aligned fields may not wind up where you expect. (I don't have time to look it up now, but I'm not convinced that even if you can get LayoutKind.Sequential to work, you'll get the result you want, i.e. an array object at the end filled with the excess data.) Commented Mar 8, 2017 at 22:34
  • You will have to use a custom marshaller. Otherwise you can't deal with variable length arrays. Here's an example: stackoverflow.com/a/38884095/103959 Commented Mar 8, 2017 at 22:46

1 Answer 1

7

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.