1

对不起这个可怕的标题,但老实说我知道我想要什么,也知道什么是错的......

基本上我有一个结构(我有 250 多个结构,但它们都遵循相同的想法),如下所示:

[StructLayout(LayoutKind.Explicit)]
public struct GenericPacket
{
    [FieldOffset(0)]
    public byte[] data;

    [FieldOffset(0)]
    public short packetid;
}

问题是字节数​​组是引用类型,而short是值类型,它不允许将fieldoffset设置为相同的内存位置......

我真的很讨厌不得不删除我写的所有结构,只是为了换一种方式。所以这是我的问题,我怎样才能以一种有效的方式使用它。基本上我要做的是:

socket.Receive(buff, 0, 0, SocketFlags.None);
GenericPacket packet = new GenericPacket();
packet.data = buff;
Console.WriteLine(packet.packetid);

它甚至拒绝编译,因为它不想生成结构 /:

在有人提出其他方法之前,我这样做的原因是它需要超高速......我可以使用 ByteReader 和其他方法(例如 BitConverter),但它需要比这快一点......

我从按位移位开始,但我需要一种更“动态”的方式来做到这一点,因为在获得数据包 ID 后,我会使用另一个结构来读取它,例如:

[StructLayout(LayoutKind.Explicit)]
public struct _03k
{
    [FieldOffset(0)]
    byte[] data;

    [FieldOffset(0)]
    short packetid;
    [FieldOffset(2)]
    short @null;
    [FieldOffset(4)]
    int major;
    [FieldOffset(8)]
    int minor;
    [FieldOffset(12)]
    int build;
}

而不是必须有很多内联的“按位狗屎”,我只是想要一种简单且非常快速的方法来做到这一点......似乎我得到了快速而不是简单/:

请帮忙!不安全的代码是可以的,但也更喜欢托管版本。

FAIL :(:只记得你可以通过装箱将值类型转换为引用类型(强制转换为类型对象)。但这确实删除了 REAL 返回类型并说它只是一个对象,无论如何 XML 文档都可以说谎关于返回类型? 悲伤地不起作用 D:

更新:好的,现在我有:

public struct GenericPacket
{
    public short packetid;

    public static GenericPacket ReadUsingPointer(byte[] data)
    {
        unsafe
        {
            fixed (byte* packet = &data[0])
            {
                return *(GenericPacket*)packet;
            }
        }
    }
}

但是每次都必须调用一个方法来转换它有点烦人:(有人有更多建议吗?

谢谢,JD

4

4 回答 4

1

您只想将数组的前两个字节转换为短字节,这会带来什么性能问题?

packetid = ((short)data[0]  << 8) | data[1];

或者如果您想要其他字节序,则反过来。

编辑:

所以你想解析多个字段。那么,不要重新发明轮子。使用 Google 的 Protocol Buffers,它非常快速高效,我怀疑你会遇到性能问题。这是一个.NET 端口。

于 2012-07-09T07:56:43.167 回答
1

我刚刚发现您可以在结构中使用固定的 araays:

[StructLayout(LayoutKind.Explicit)]
unsafe struct Union
{
    [FieldOffset(0)]
    public short x;
    [FieldOffset(0)]
    public fixed byte y[2];
}

初始化:

var u = new Union();
byte[] y = new byte[2]; //your original array here
int len = y.Length;
unsafe
{
    fixed (byte* s= y)
    {
        byte* source = s;
        byte* dest = u.y;
        for (int i = 0; i < len; i++)
        {
            *dest++ = *source++;
        }
    }
}
于 2012-07-09T08:22:50.083 回答
0

我最终确定的是一个带有隐式转换运算符的结构,该运算符称为 ReadByPointer 方法。

public struct GenericPacket
{
    public short packetid;

    public static GenericPacket ReadUsingPointer(byte[] data)
    {
        unsafe
        {
            fixed (byte* packet = &data[0])
            {
                return *(GenericPacket*)packet;
            }
        }
    }

    static public implicit operator GenericPacket(byte[] value) 
    {
        return GenericPacket.ReadUsingPointer(value);
    }
}

这允许您执行以下操作:

GenericPacket packet = bufferFromReceive;

谢谢-jD

于 2012-07-09T08:22:24.553 回答
0

在这个特定的例子中,你可以这样做:

[StructLayout(LayoutKind.Explicit)]
struct byte_array
{
    [FieldOffset(0)]
    public byte byte1;

    [FieldOffset(1)]
    public byte byte2;

    [FieldOffset(0)]
    public short packetid;
}

但总的来说,Buffer.BlockCopy 可能是更好的解决方案。

于 2012-07-09T07:48:22.787 回答