没有在Marshal.PtrToStructure

时间:2017-09-28 08:12:28

标签: c# arrays delphi

我已经提出了基于Reading binary file from delphiProper struct layout from delphi packed record

的当前c#结构

现在我的问题是我没有从文件中获取正确的值

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct test {
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
  string field1;
  ...
}

她是德尔福记录

char3 = Array[0..2] of Char;

test = Record
  field1: char3;
  ...

编辑:

正如我在大卫回答的评论中所说。问题是我缺少字符串的一部分。在按照David的回答使用byte[]代替string后,我的代码现在正在运行。

以防有人偶然发现这个delphi record to C#,这有点令人困惑,因为它假定delphi字符串是以空值终止的。

同样关于StructLayout Pack属性,只要尝试将此设置为1,即使您要转换的Delphi记录没有指明它。如果我遗漏了有关Pack的内容,请在评论中更正我。感谢

至于我的最终结构:

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct test {
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  byte[] field1;
  ...
}

1 个答案:

答案 0 :(得分:1)

问题中代码的正确性完全取决于Char

  • 在Delphi 2009及更高版本中,CharWideChar的别名,是16位类型。
  • 在早期版本中,CharAnsiChar的别名,是8位类型。

因此,如果您使用的是Delphi 2009之前的Delphi版本,那么您的代码是正确的。否则您的C#代码应该用CharSet.Ansi替换CharSet.Unicode

另一个区别是C#代码坚持要求数组为空终止,而Delphi代码则不需要。因此,如果您的Delphi代码想要将所有三个元素都用作非空值,那么您需要避免在C#端使用string。它会变成:

[StructLayout(LayoutKind.Sequential)]
struct test {
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  byte[] field1;
  ...
}

用于Unicode前Delphi或

[StructLayout(LayoutKind.Sequential)]
struct test {
  [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
  char[] field1;
  ...
}

for Unicode Delphi。