4

TCP ソケット経由でネットワーク デバイスからデータを読み取り、これを C# 構造に変換するサービス (C#) を開発する必要があります。

私は、このすべてを行っている既存の古い Delphi アプリケーションに基づいており、C# でロジックを移行する必要があります。

編集: 元のデータ構造の C ソースからスナップショットを取得しました:

struct _RequestMsgStruct
{
    UCHAR           request_ver; //In DELPHI it is represented as Byte
    USHORT          mac_addr[3];    /* MAC Address */
    UINT            product_type; //In DELPHI - Cardinal
    UCHAR           supply_type; //In DELPHI - Byte
    short           reserved0; //In DELPHI - SmallInt
    UCHAR           oper_ver[4]; //In DELPHI - CARDINAL !!!
    USHORT          brd_id; //In DELPHI - WORD
    unsigned short  exp_id1; //In DELPHI - WORD

    //In DELPHI - string[15]; //Array [0..15] of char;
    UCHAR           serial_no[16]; /* Serial Number. 16th char have to be NULL */ 
    UCHAR           _name[32]; /* Name */ //Length of payload may vary //In DELPHI - string[31]

    float           data_avg; //In DELPHI - Single
    ULONG           key[5]; //In DELPHI - array [0..19] of Byte
}__attribute__ ((packed));

さまざまなタイプの 200 以上のフィールドを持つ Delphi Packed レコードがあります...おおよそ次のようになります。

  TREC_DATA = packed record
      ID            : Byte;
      MAC_ADDRESS   : array [0..5] of Byte;
      fieldCard     : cardinal;
      fieldSI       : SmallInt; 
      fieldW        : WORD;
      SERIAL_NUMBER : string[15]; //Array [0..15] of char;
      fieldSingle   : Single;
      fieldArrOfB   : array [0..19] of Byte;
    end;

Delphi でバイト配列を構造体に移動するには、次のコードがあります。

Move(inBytesArr[StartIdx], DelphiStruct, aMsgSize)

文字列ファイル (SERIAL_NUMBER など) を変換するには、次のようなコードもあります。

var
  pc: Pchar;
...
pc := @inBytesArr[StartIdx + SerialN_Pos_Idx];
DelphiStruct.SERIAL_NUMBER := pc;

私はそのような変換に初めて対処しましたが、どこから始めればよいかわかりません:

  • この構造をC#に変換するには? --LayoutKind.SequentialまたはLayoutKind.Explicit、または wiyhout[FieldOffset(N)]属性を使用する必要がありますか? -- ターゲットの C# 構造体でバイト配列を宣言するにはどうすればよいですか:fixedバッファとして、または[MarshalAs(UnmanagedType.ByValArray...)]属性を使用して?

  • Marshal.PtrToStructureGCHandle.Alloc(bytes, GCHandleType.Pinned) +を使用して、入力バイト配列を最終的な C# 構造にマーシャリングするより良い方法はどれAddrOfPinnedObjectですか

少なくとも、私がどこから始めなければならないかを控えめにするための出発点を得るのを手伝ってください。

4

1 に答える 1

4

デフォルトでは、Delphi のパック レコードはフィールドを 1 バイト境界で整列します。
したがって、次のようなものを使用する必要があります。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct TREC_DATA
{
      public byte ID;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
      public byte[] MAC_ADDRESS;
      public uint fieldCard;
      public short fieldSI;
      public ushort fieldW;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
      public byte[] SERIAL_NUMBER;
      public float fieldSingle;
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
      public byte[] fieldArrOfB;    
} 

私が確信していない唯一のこと (Deplhi なしでは今はテストできません) は、SERIAL_NUMBER フィールドです。

更新後:元の SERIAL_NUMBER は null で終わる文字列です。

于 2012-09-28T07:18:46.067 に答える