gpt4 book ai didi

c# - 我想将联合用作带字节数组的 C#

转载 作者:太空狗 更新时间:2023-10-30 01:22:42 25 4
gpt4 key购买 nike

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

所以我想用 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 可以解决这个问题?如果我将它与继承一起使用,是否可能?

附言抱歉我的英语不好

最佳答案

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

其他方法是 - 只是忘记结构中的这个数组,并使用 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);
}

关于c# - 我想将联合用作带字节数组的 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13001327/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com