3

私が変更している一部のコードは、構造体を広範囲に使用して、バイト配列との間でロードすることにより、一部の工場設備と通信します。

これは、そのような構造体の非常に単純化された例です。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct K_FOO
{
    public byte a_byte;    // 1 byte
    public BYTE3_TYPE b3;  // 3 bytes
    public int num;        // happens to be 4 bytes
}

BYTE3_TYPEは次のようになります...

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class BYTE3_TYPE
{
    [System.Runtime.InteropServices.MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
    public byte[] L = new byte[3];
}

私がするだけなら

    K_FOO origFoo = new K_FOO();

intとbyteは0に初期化されます。これらはネイティブ型であるためと思いますが、バイト配列b3は* un *initialized-すべてnullです。たとえば、明示的にロードする必要があります。

    BYTE3_TYPE b3 = new BYTE3_TYPE();
    origFoo.b3 = b3;

...構造体はパラメーターのないコンストラクターを使用しないため、代替案は考えられませんでしたが、実際の構造体は巨大です。

しかし、私は何か面白いことに気づきました。これらの構造体をバイト配列との間でコピーするルーチンがあります。例えば ​​。。。

   public static T ByteArrayToStructure<T>(byte[] buffer) where T : struct
    {
        int length = buffer.Length;
        IntPtr ptr = Marshal.AllocHGlobal(length);   // allocate (length) bytes
        Marshal.Copy(buffer, 0, ptr, length);  // copies into UNmanaged space
        T result = (T)Marshal.PtrToStructure(ptr, typeof(T));
        Marshal.FreeHGlobal(ptr);
        return result;
    }

...そして私がそれを呼ぶなら...

    K_FOO retFoo = ByteArrayToStructure<K_FOO>(buffer.bytes);

...結果の構造体は完全に初期化されて返され、バイト配列内のバイトにはすべてスペースが割り当てられているため、明らかにPtrToStructure()呼び出しでロードできます。これは、.Netがそのような構造体を初期化する方法を「知っている」ことを意味します。では、.Netにそれを実行させて、数百行の明示的な初期化コードを記述しないようにする方法はありますか?前もって感謝します!

4

1 に答える 1

6

クラスの代わりに構造体を作成するBYTE3_TYPEと、デフォルトのコンストラクター(を呼び出す K_FOO origFoo = new K_FOO();)によって全体が正しくゼロに初期化されます。

これは、既存の仕様と一致させ、これをカスタムハードウェアに渡そうとしている場合にも、正しいアプローチである可能性があります。

于 2013-02-04T17:08:35.283 に答える