1

もう一度、C++ プログラムから UDP 経由で構造体を受信して​​います。構造体を C# に移植しました。例:

[Serializable]
struct sample
{
public int in;
public byte[] arr;
public int[] arr2;
public float fl;
}

では、デシリアライザーは、一方の配列がいつ終了し、もう一方の配列が開始するかをどのように認識しているのでしょうか? どういうわけか配列の大きさを指定できますか? これによりコードが安全でなくなるため、固定を使用したくありません。また、構造体にはパラメーターのないコンストラクターを含めることが許可されていないため、コンストラクターも使用できません。

助言がありますか?

//編集:

配列の長さは 32 と 4 であることが知られています。問題は、この情報をデシリアライザーに渡す方法がわからないことです

次に、送信者は C++ であり、次のように機能します。

char* pr = &sample;
int i=0;
while (i<sizeof(sample))
{
 udp.send(*(pr+i))
 i++;
}
4

3 に答える 3

3

長さが事前に定義された長さであることがわかったので、次のステートメントがより明確になります。

この情報をデシリアライザに渡す方法がわかりません

実際、それは無意味になります。ここで役立つ定義済みのシリアライザーはありません。次の 2 つのオプションがあります。

A: 独自のシリアライザーを作成し、フォーマットがわかったところでデータを処理します。おそらく以下を使用しBinaryReaderます。

using(var reader = new BinaryReader(source)) {

    int in = reader.ReadInt32();
    byte[] arr = reader.ReadBytes(32);
    int[] arr2 = new int[4];
    for(int i = 0 ; i < 4 ; i++) arr2[i] = reader.ReadInt32();
    float fl = reader.ReadSingle();

    var obj = /* something involving ^^^ */
}

B: 56 バイトをバッファリングし、非常に厄介な // ポインターバンギング コードをunsafe使用fixedする

最初に強くお勧めします。特に、これにより、必要に応じてエンディアンに対処することもできます。

あなたにとって神聖なすべての名において、これをしないでください:

using System;
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
unsafe struct sample
{
    [FieldOffset(0)] public int @in;
    [FieldOffset(4)] public fixed byte arr[32];
    [FieldOffset(36)] public fixed int arr2[4];
    [FieldOffset(52)] public float fl;    
}

static class Program
{
    unsafe static void Main()
    {
        byte[] buffer = new byte[56];
        new Random().NextBytes(buffer); // some data...

        sample result;
        fixed(byte* tmp = buffer)
        {
            sample* ptr = (sample*) tmp;
            result = ptr[0];
        }

        Console.WriteLine(result.@in);
        Console.WriteLine(result.fl);
    }    
}

より大きなバッファーの場合、インデックスによってアクセスされるptrmultiple の安全でない配列として扱うことができます。sample

int @in = ptr[i].@in;

(等)

しかし、正直なところ...それには非常に多くの「悪」があり、正直なところ、どこから始めればよいかわかりません...ただ...そこにあるすべての行が何をしているのかを完全に知っていない限り、以前にそれを行ったことがあり、すべてのトラップを理解する...それについて考えないでください

于 2012-06-26T10:26:40.600 に答える
1

これは、構造体をネットワーク経由で渡すために使用される形式によって異なります。

json だとすると、各フィールドにはキーがあり、配列は [] で囲まれます。

xml だとすると、子ノードを持つ arr ノードが期待されます。

任意の形式の場合は、その形式を知る必要があります。

デシリアライザにはいくつかのデフォルトの動作がありますが、渡されたデータがデフォルトの形式でない場合は、デシリアライズする方法を正確に伝える必要があります。

于 2012-06-26T08:18:15.633 に答える
1

また、生データはどのように文書化されていますか? ここで何か伝えたいことがあると思います。たとえば、フォーマットは(純粋な例です)と言うと思います。

  • 4 バイト NBO Int32 ( in)
  • 4 バイト NBO Int32 (長さarr)
  • len バイト ( arr)
  • 4 バイト NBO (長さarr2)
  • 4 * len バイト ( arr2、それぞれ NBO Int32 内)
  • 4 バイト IEEE-754 ( fl)

フォーマットを知る必要があります。

編集: C++ 配列が既知の固定長である場合、それらの長さを事前に知っておく必要があります。

于 2012-06-26T08:19:40.307 に答える