2

古い Visual BASIC プログラムを C# に変換しています。このプログラムは、シリアルまたはイーサネット回線を介して一部の産業機械にメッセージを送信します。これを行うために、メッセージのバイト配列を作成します。

問題は、多くの(~50) の異なるメッセージ形式があり、それぞれがVB6でユーザー定義型として定義されていることです。例えば。

Public Type K_QCHECK
    Header As K_HEADER3
    Count As LNG4
    crc As INT2
End Type

(LNG4 と INT2 はカスタム タイプです) 自動変換ツールを使用して VB6 コードを実行すると、C# 構造体が得られます。

public struct K_QCHECK
{
     public K_HEADER3 Header;
     public LNG4 Count;
     public INT2 crc;
}

しかし、古い VB6 コードは、LSet を使用してこれらをバイト配列にコピーしていました。これは、型がメモリの連続したブロックを表すという仮定に依存していました。しかし、C# では、コンパイラによってメモリ内に配置される方法は、プログラマがアクセスできない実装の詳細であると想定されています。

では、これらの異なる構造体の内容をバイト配列に取得する最良の方法は何でしょうか? それぞれをクラスにして、それに CopyToByteArray メソッドまたは演算子を与えることもできますが、これらは 50 個あるので、大変な作業のように思えます。提案をお寄せいただきありがとうございます。

4

2 に答える 2

3

これはおそらく正しい解決策ではありませんが、構造体がメモリにどのように配置されるかを明示的に定義できるStructLayoutAttributeがあります。

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute%28v=vs.110%29.aspx

于 2013-01-23T17:28:22.743 に答える
1

structureこれらのコードを使用すると、任意の配列表現とその配列表現の間で変換できますbyte[]。構造ごとに個別のメソッドを実装する必要はありません。

    public static byte[] StructureToByteArray<T>(T structure) where T:struct
    {
        int len = Marshal.SizeOf(structure);

        byte[] result = new byte[len];

        IntPtr ptr = Marshal.AllocHGlobal(len);

        Marshal.StructureToPtr(structure, ptr, true);

        Marshal.Copy(ptr, result, 0, len);

        Marshal.FreeHGlobal(ptr);

        return result;
    }

    public static T ByteArrayToStructure<T>(byte[] buffer) where T:struct
    {
        //int len = Marshal.SizeOf(typeof(T));
        int length = buffer.Length;

        IntPtr i = Marshal.AllocHGlobal(length);

        Marshal.Copy(buffer, 0, i, length);

        T result = (T)Marshal.PtrToStructure(i, typeof(T));

        Marshal.FreeHGlobal(i);

        return result;
    }
于 2013-01-23T17:32:52.200 に答える