我正在尝试将网络数据包发送到硬件设备。我想使用一种巧妙的、面向对象的方法,这样我就可以在更高层次上使用它。数据包有几个可变长度的字段。显然字节布局是很有讲究的。
这是一个表示我需要发送的数据包的结构:
[StructLayout(LayoutKind.Sequential)]
public struct Packet
{
public UInt16 Instruction;
public UInt16 Length; //length of data field
public UInt32 SessionHandle;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] SenderContext;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] MessageData;
}
MessageData[]
可以是任意长度,我将其固定为 8 个字节作为开始。
这是我创建一个 byte[]
以通过 Socket 发送它的尝试:
public static byte[] ToBytes(Packet ep)
{
Byte[] bytes = new Byte[Marshal.SizeOf(typeof(Packet))];
GCHandle pinStructure = GCHandle.Alloc(ep, GCHandleType.Pinned);
try
{
Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
return bytes;
}
finally
{
pinStructure.Free();
}
}
但我收到:
ArgumentException : Object contains non-primitive or non-blittable data.
我认为在结构中设置 SizeConst
会解决这个问题?无论如何,我比这更迷茫,因为硬件设备需要一个可变长度的数据包,我想利用它。
我可以手动将数据包逐字节放在一起,一切都很好。但我知道必须有更好的方法,而且我一定是走错了路。
有什么想法吗?
最佳答案
CLR 不允许您使用具有与引用类型重叠的字段的结构。你的情况下的两个数组。它与垃圾收集器非常不兼容,它无法跟踪对象引用。并且会非常不安全,因为它允许后门进入堆,直接操纵对象引用的值。
在您的特定情况下这样做没有意义,因为两个数组重叠并且大小完全相同。一个人就能很好地完成工作。
关于c# - 将可变长度结构转换为 byte[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3736589/