2017-11-06 7 views
2

に詰めたレコードと同じように整列化配列をバイトを:はC#構造体は、私はこのようなバイト配列を生成し、デルファイ、2007年に書かれたレガシーアプリケーションを持っているデルファイ

command_data = packed record 
    direction  : word; 
    name   : array [0..9] of char; 
end; 

command_header = packed record 
    length  : word; 
    data1  : word; 
    data2  : cardinal; 
end; 

command_data_container = packed record 
    data   : command_data; 
    containerId : word; 
end; 

function Generate(name: string)boolean; 
var 
    header : command_header; 
    container : command_data_container; 
    charArrayName: array [0..9] of char; 

begin 
    charArrayName = array [0..9] of char; 

    for I := 0 to Length(name) - 1 do begin 
    charArrayName[i] := name[i+1]; 
    end; 
    charArrayName[i+1] := #0; 

    header.length := sizeof(header) + sizeof(container); 
    header.data1 := 0; 
    header.data2 := 1; 

    container.data.direction := 1; 
    container.data.name  := charArrayName; 
    container.containerId := 1; 

    stream := TMemoryStream.Create; 
    stream.WriteBuffer(header, SizeOf(header)); 
    stream.WriteBuffer(container, SizeOf(container)); 
    //... 
end; 

私はC#でこの部分を書き換える必要があります。私は今のところこれを得た:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
unsafe struct command_data 
{ 
    public ushort direction; 
    public fixed char name[10]; 
} 

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
unsafe struct command_header 
{ 
    public ushort length; 
    public ushort data1; 
    public ulong data2; 
}  

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
struct command_data_container 
{ 
    public command_data data; 
    public ushort containerId; 
} 

public bool Generate(string name) 
{ 
    name = name + Char.MinValue; // Add null terminator. 
    char[] charArrayName = agentId.ToCharArray(); 

    unsafe 
    { 
     command_header header; 
     command_data_container command; 

     header.data1 = 0; 
     header.data2 = 1; 
     header.length = (ushort)(sizeof(command_header) + sizeof(command_data_container)); 


     command.data.direction = 1; 
     *command.data.name = charArrayName[0]; 

     for (int i = 1; i < charArrayName.Length; i++) 
     { 
      *(command.data.name + i) = charArrayName[i]; 
     } 
     command.containerId = 1; 

     var headerBytes = StructToBytes<command_header>(header); 
     var commandBytes = StructToBytes<command_data_container>(command); 

     byte[] combined = new byte[headerBytes.Length + commandBytes.Length]; 
     Buffer.BlockCopy(headerBytes, 0, combined, 0, headerBytes.Length); 
     Buffer.BlockCopy(commandBytes, 0, combined, headerBytes.Length, commandBytes.Length); 

     //combined should have the same data as the stream in the delphi code 

    } 
} 


public static byte[] StructToBytes<T>(T structure) where T : struct 
{ 
    int size = Marshal.SizeOf(structure); 
    byte[] rawData = new byte[size]; 
    GCHandle handle = GCHandle.Alloc(rawData, GCHandleType.Pinned); 
    try 
    { 
     IntPtr rawDataPtr = handle.AddrOfPinnedObject(); 
     Marshal.StructureToPtr(structure, rawDataPtr, false); 
    } 
    finally 
    { 
     handle.Free(); 
    } 
    return rawData; 
} 

私はバイト配列に構造体を変換するために、いくつかの方法を試してみましたが、それらのどれもDelphiのコードと同じ結果を再現していません。

StructToBytes方法はここから借りている:C# performance - Using unsafe pointers instead of IntPtr and Marshal

私はまた、SOからメソッドをマーシャリングを他のいくつかを試してみましたが、何も働きました。 どうしたのですか?

+0

Delphi 2007 CharがAnsiCharであり、C#でUnicodeであることはご存知ですか? –

+0

c#のCharは2バイトですが、C++では1バイトです。したがって、C#ではnew byte [10]を使用します。また、配列は '\ 0'(0x00)で終わらなければなりません。私は通常、以下を使用します:Encoding.UTF8.GetBytes( "JohnSmith \ 0"); – jdweng

+1

**これをC#で**書き直す必要がある場合は、なぜinteropとマーシャリングについて気にしますか?ちょうど同じバイト数を生成してください。あまりにも難しいことはできません。 –

答えて

2
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] 
struct command_data 
{ 
    public ushort direction; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] 
    public string name; 
} 
+0

いくつかの説明はここでいいだろう –

関連する問題