C#将字节解析为struct sequential

liv*_*ve2 4 c# arrays struct

我尝试解析一个字节数组到struct但它不能用于Sequential.Sequential结构中的值是错误的,但它与Explicit结构一致吗?我需要顺序字节数组没有固定长度.DwLength字段是数据字段的大小.

  • MessageType 128(顺序128)
  • DwLength 20(顺序33554432)
  • 插槽0(顺序0)
  • Seq 0(顺序0)
  • 状态2(顺序59)
  • 错误0(顺序143)
  • ChainParameter 0(顺序128)

测试代码

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);
Run Code Online (Sandbox Code Playgroud)

struct RdrToPcDataBlock顺序

[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;
}
Run Code Online (Sandbox Code Playgroud)

struct RdrToPcDataBlock明确

[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;
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 6

当你这样[StructLayout(LayoutKind.Sequential)]做时[StructLayout(LayoutKind.Sequential, Pack=0)],将使用默认打包来处理进程的位数(对于32位为4,对于64位为8).要获得您想要的行为,您需要通过设置明确表示您不需要任何填充[StructLayout(LayoutKind.Sequential, Pack=1)]

更新:您仍然会遇到可变长度字节数组的问题.请参阅Jean-Bernard Pellerin评论

您将不得不使用自定义marshaller.否则你无法处理可变长度数组.这是一个例子:https://stackoverflow.com/a/38884095/103959