2017-03-08 55 views
4

我尝试解析一个字节数组结构,但它不适用于Sequential。 Sequential结构中的值是错误的,但它对Explicit结构是否正确?我需要顺序的字节数组没有固定的长度。 DwLength字段是数据字段的大小。C#解析字节结构顺序

  • 消息类型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); 

结构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; 
} 

结构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; 
} 

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); 
    } 
} 
+0

_“值是错误的_” - 请更具体。 _“错”_以什么方式?你会得到什么结果?你期望的结果是什么?请提供一个可靠地再现问题的良好[mcve],并更准确地解释问题。还要注意''LayoutKind.Sequential'受制于包装规则,所以不符合的字段可能不会达到您的预期。 (我现在没有时间去查看它,但是我不相信即使你可以使用'LayoutKind.Sequential'工作,你也会得到你想要的结果,也就是说在最后填充一个数组对象与多余的数据。) –

+0

你将不得不使用自定义编组器。否则,你不能处理可变长度的数组。以下是一个示例:http://stackoverflow.com/a/38884095/103959 –

回答

5

这样做[StructLayout(LayoutKind.Sequential)]是一样做[StructLayout(LayoutKind.Sequential, Pack=0)]这将使用默认的填料的过程的位数(4用于32位和8为64位)。为了让您想让你需要明确地说,你不希望任何填充通过设置[StructLayout(LayoutKind.Sequential, Pack=1)]

更新行为:你仍然要与你的可变长度的字节数组中运行的问题。请参阅comment by Jean-Bernard Pellerin

您将不得不使用自定义编组器。否则,你不能处理可变长度的数组。这里有一个例子:https://stackoverflow.com/a/38884095/103959