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:

更新: OK、今私は持っています:

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

配列の最初の2バイトをshortに変換したいだけですが、パフォーマンスの問題はどのように発生しますか?

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

または、他のエンディアンが必要な場合は、その逆です。

編集:

したがって、複数のフィールドを解析する必要があります。それなら、車輪の再発明をしないでください。GoogleのProtocolBuffersを使用してください。これは非常に高速で効率的であり、パフォーマンスの問題が発生することはないと思います。これが.NETポートです。

于 2012-07-09T07:56:43.167 に答える
1

構造体で固定araayを使用できることがわかりました。

[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

この特定の例では、これを行うことができます。

[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 に答える
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 に答える