C#结构到字节数组的编组方式与Delphi中打包记录的编组方式相同

C#结构到字节数组的编组方式与Delphi中打包记录的编组方式相同,c#,arrays,delphi,struct,marshalling,C#,Arrays,Delphi,Struct,Marshalling,我有一个用Delphi 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

我有一个用Delphi 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;
}
[StructLayout(LayoutKind.Sequential,Pack=1)]
不安全的结构命令\u数据
{
公共卫生服务方向;
公共固定字符名[10];
}
[StructLayout(LayoutKind.Sequential,Pack=1)]
不安全的结构命令\u头
{
公共长度;
公共卫生数据1;
公共乌龙数据2;
}    
[StructLayout(LayoutKind.Sequential,Pack=1)]
结构命令\u数据\u容器
{
公共命令数据;
公共集装箱运输;
} 
公共布尔生成(字符串名称)
{
name=name+Char.MinValue;//添加空终止符。
char[]charArrayName=agentId.ToCharArray();
不安全的
{
命令头;
命令\数据\容器命令;
header.data1=0;
header.data2=1;
header.length=(ushort)(sizeof(命令头)+sizeof(命令数据容器));
command.data.direction=1;
*command.data.name=charArrayName[0];
for(int i=1;i
我尝试了几种方法将结构转换为字节数组,但没有一种方法能再现与Delphi代码相同的结果

StructToBytes方法借用自此:

我还尝试了其他一些编组方法,但没有任何效果。
我做了什么错事?< /P>你知道Delphi 2007 char是ANSICAR,C中是Unicode?Car中的char是两个字节,而C++中是一个字节。因此在c#中使用:新字节[10]。阵列也必须以“\0”(0x00)终止。我通常使用:Encoding.UTF8.GetBytes(“JohnSmith\0”);如果必须用C#重写,那么为什么要关心互操作和编组?只需生成相同数量的字节。不难。我同意这里的@Rudy。直接写入字节流更简单。显然,这里的大问题是已经确定的围绕char的大小问题。我还想指出的是,您的Delphi代码已经具备了缓冲区溢出的条件。@jdweng
编码。这里的默认值与Delphi代码相匹配。我没有看到任何证据表明输入字符串是UTF-8编码的。ANSI是Delphi2007的标准。这里有一些解释会很好
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
struct command_data
{
    public ushort direction;
    [MarshalAs( UnmanagedType.ByValTStr, SizeConst = 10)]
    public string name;
}