我尝试解析一个字节数组到struct但它不能用于Sequential.Sequential结构中的值是错误的,但它与Explicit结构一致吗?我需要顺序字节数组没有固定长度.DwLength字段是数据字段的大小.
值
测试代码
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)
当你这样[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