繁体   English   中英

我想使用union作为C#和字节数组

[英]I'd like to use union as C# with byte array

我对串行通信中的消息解析有所了解,有很多种不同形式的数据包。 但它们都是由字节数组发送的。

所以我想用union来解析每条消息。 但它运作不佳。 下面的代码是我遇到错误的示例代码

[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才能解决这个问题? 如果我继承使用它,是否可能?

PS抱歉我的英语不好

我不是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);
}

其他方法是 - 只是忘记struct中的这个数组,并使用Marshal.Copy处理解析:

[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);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM