I';我想使用union作为带有字节数组的C#
我对串行通信中的消息解析有了概念,有很多种不同形式的数据包。但它们都是通过字节数组发送的 所以我想用union来解析每条消息。 但效果不太好。 下面的代码是我出错的示例代码I';我想使用union作为带有字节数组的C#,c#,union,packets,C#,Union,Packets,我对串行通信中的消息解析有了概念,有很多种不同形式的数据包。但它们都是通过字节数组发送的 所以我想用union来解析每条消息。 但效果不太好。 下面的代码是我出错的示例代码 [StructLayout(LayoutKind.Explicit, Size=12)] public struct UnionPacket { [MarshalAs(UnmanagedType.ByValArray, SizeConst=12)] public byte[] data; [Fiel
[StructLayout(LayoutKind.Explicit, Size=12)]
public struct UnionPacket
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=12)]
public byte[] data;
[FieldOffset(0)]
public float Time;
[FieldOffset(4)]
public Int16 CoordX;
[FieldOffset(6)]
public Int16 CoordY;
[FieldOffset(8)]
public byte Red;
[FieldOffset(9)]
public byte Green;
[FieldOffset(10)]
public byte Blue;
[FieldOffset(11)]
public byte Alpha;
}
如果这是可能的,它会非常高兴,但事实并非如此。此代码发生TypeLoadException“…因为它包含偏移量0处的对象字段,该字段未正确对齐或被非对象字段重叠。”
所以我修改了一些类似这样的代码
[StructLayout(LayoutKind.Explicit, Size= 12)]
public struct UnionPacket
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
[FieldOffset(0)]
public byte[] data;
//[FieldOffset(0)]
//public float Time;
[FieldOffset(4)]
public Int16 CoordX;
[FieldOffset(6)]
public Int16 CoordY;
[FieldOffset(8)]
public byte Red;
[FieldOffset(9)]
public byte Green;
[FieldOffset(10)]
public byte Blue;
[FieldOffset(11)]
public byte Alpha;
}
对于测试,我只是禁用了偏移量为0的时间字段,这并没有发生异常。但是,如果我更改其他字段,它不会更改字节数组。我认为字节数组的实际内存位置是在另一堆中分配的,所以不能这样做
有没有办法用C语言解决这个问题?只有C++或C可以解决这个问题?
如果我把它和继承一起使用,有可能吗
另外,很抱歉我的英语不好我不能100%确定你想做什么,但是: 第一种方法是,如果将数组与固定/不安全关键字一起使用,则可以将数组存储在结构内部。我不知道这对你来说是否可行。因此,拥有这样的代码应该是可行的:
[StructLayout(LayoutKind.Explicit, Size = 12)]
public unsafe struct UnionPacket
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
[FieldOffset(0)]
public fixed byte data[12];
[FieldOffset(0)]
public float Time;
[FieldOffset(4)]
public Int16 CoordX;
[FieldOffset(6)]
public Int16 CoordY;
[FieldOffset(8)]
public byte Red;
[FieldOffset(9)]
public byte Green;
[FieldOffset(10)]
public byte Blue;
[FieldOffset(11)]
public byte Alpha;
}
当然,您必须在VS中启用不安全的代码块,并使用包装结构:
unsafe
{
var u = new UnionPacket();
for (byte i = 0; i < 12; i++)
{
u.data[i] = i;
}
Console.WriteLine(u.Time);
Console.WriteLine(u.CoordX);
Console.WriteLine(u.CoordY);
Console.WriteLine(u.Red);
Console.WriteLine(u.Green);
Console.WriteLine(u.Blue);
Console.WriteLine(u.Alpha);
}
谢谢,我使用了第二种方法,因为使用固定数组很难替换数据,谢谢。
[StructLayout(LayoutKind.Explicit, Size = 12)]
public struct UnionPacket2
{
[FieldOffset(0)]
public float Time;
[FieldOffset(4)]
public Int16 CoordX;
[FieldOffset(6)]
public Int16 CoordY;
[FieldOffset(8)]
public byte Red;
[FieldOffset(9)]
public byte Green;
[FieldOffset(10)]
public byte Blue;
[FieldOffset(11)]
public byte Alpha;
}
static void Main(string[] args)
{
var len = Marshal.SizeOf(typeof(UnionPacket2));
var buffer = new byte[len];
for (byte i = 0; i < len; i++)
{
buffer[i] = i;
}
var ptr = Marshal.AllocHGlobal(len);
Marshal.Copy(buffer, 0, ptr, len);
var u = (UnionPacket2)Marshal.PtrToStructure(ptr, typeof(UnionPacket2));
Marshal.FreeHGlobal(ptr);
Console.WriteLine(u.Time);
Console.WriteLine(u.CoordX);
Console.WriteLine(u.CoordY);
Console.WriteLine(u.Red);
Console.WriteLine(u.Green);
Console.WriteLine(u.Blue);
Console.WriteLine(u.Alpha);
}