2

古い C++ アプリを C# に移植する作業を行っていますが、私のソリューションが実際に実現可能かどうかはわかりません。

頭痛の種のほとんどは、アプリのファイル形式が、本質的にファイルにダンプされた (かなり大きな) 構造の一部に過ぎないことです。楽しい部分は、システムに関係なく、整数がビッグエンディアンの順序である必要があるということです。そこで、バイト オーダーを反転するためのユーティリティ メソッドをまとめ、多数の固定サイズ バッファーを使用して C++ レイアウトを複製する構造を構築しました。この時点でのインポートは、ファイルをメモリにコピーしてMarshal.PtrToStructureを使用するのと同じくらい簡単です。これは、手動で読み込むよりもはるかに簡単ですが、構築時にバイト オーダーを反転させることはできません。

そのため、フォーマットは、個別のバッファと固定バッファの両方で、短い変数にかなり大きく依存しています。非常に多くの固定ステートメントをまとめて、バッファーをフリップ用にピン留めする過程で、私は不穏な考えを持っていました。

私が間違っていない限り、バッファーの 1 つだけを固定すると、構造全体が固定されます (構造の一部を残りの部分から離して再配置しても意味がありません)。だから、私はこのようなことを試しました:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct Example
{
    short value1;
    fixed short value2[10];
    short value3;
    fixed short value4[20];

    public void FlipEndianness()
    {
        fixed (short* ptr = &value1)
        {
            Utility.FlipShorts(ptr, 32);
        }
    }
}

アイデアは、ユーティリティメソッドがポインターとカウントで機能し、ポインターを配列であるかのように反復処理することです。最初はバッファーを反転するために書きましたが、ここで値を見ました。理論的には、これは適切に機能しているようです。すべての変数は、それほど手間をかけずに 1 回の呼び出しで反転されます。私が知る必要があるのは、私のコンセプトが実際に安全かどうかです。すべてを手動で固定するのは非常に面倒です。構造が巨大であると言いましたか?

変数を固定すると、構造全体が固定され、この種のトリックが可能になりますか、それとも、これがメモリをぎゅうぎゅう詰めにしなかったのは幸運でしょうか? これまでのところ、私のテストではイエスと言われていますが、確実に言うことはできません. 私はむしろ私にこれを爆破させたくない.

4

1 に答える 1

1

これが C# で安全に実行できることを示すリソースは、私が知っている限りではありません。GC には、構造体のフィールドを固定したままにし、構造体の他のフィールドを移動できるようにするメカニズムはありません。このような固定ステートメントは、固定された内部ポインターを作成します。GC は、そこからオブジェクト ルートを検出するのに十分スマートです。内部ポインターは、C++/CLI の文献でのみ言及されています。これは、内部ポインターを直接宣言できる言語です。interior_ptr<>キーワード。これは、Mono などの別の CLR 実装では必ずしもうまく機能しないことに注意してください。YMMV。それ以外の場合は、C++/CLI の方が優れた武器です。少なくとも、C# で書き直すことなく、元の C または C++ 宣言を使用できます。そして、ネイティブ構造体への安定したポインターが得られます。

そもそも問題になることはありません。実際のオブジェクトの固定は、構造体が GC ヒープに割り当てられた参照型の一部である場合にのみ必要です。コードがどのように見えるかはわかりませんが、データを読み取って変換するメソッドで、そのような構造体をローカル変数として保持するのが賢明な方法です。このような値型はスタックに割り当てられ、安定したアドレスを持ちます。

このコードには安全でない部分がたくさんあることに注意してください。コンパイラもランタイムも、magic 32 値を誤って使用することについて何もできません。ファイル データ変換コードの最適化が役立つことはほとんどありません。データを読み取るコストは、解釈するよりも桁違いに高くなります。リフレクションを使用してフィールドを元に戻すことは合理的であるため、その方法で間違いを犯すことはありません。Jon Skeet の EndianBinaryReader についても言及する必要があります。

于 2014-03-11T11:40:18.997 に答える