简体   繁体   English

在 Marshal.PtrToStructure 中没有获得正确的字符数

[英]Not getting correct number of characters in Marshal.PtrToStructure

I have come up with current c# struct based on Reading binary file from delphi and Proper struct layout from delphi packed record我已经根据从 delphi 中读取二进制文件从 delphi 打包记录中正确的结构布局提出了当前的 c# 结构

Now my problem is I am not getting the correct values from the file现在我的问题是我没有从文件中获得正确的值

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

Hers is the delphi record她的就是德尔福记录

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

test = Record
  field1: char3;
  ...

Edit:编辑:

As I said in the comment on David's answer.正如我在对大卫回答的评论中所说的那样。 The problem is that I am missing parts of the string.问题是我缺少部分字符串。 After following David's answer which is to use byte[] instead of string , my code is now working.按照大卫的答案使用byte[]而不是string ,我的代码现在可以工作了。

Just in case someone stumbled upon this delphi record to C# , which is a bit confusing since it assumes that the delphi strings are null-terminated.以防万一有人在C# 中偶然发现了这条delphi 记录,这有点令人困惑,因为它假定 delphi 字符串以空字符结尾。

Also regarding the StructLayout Pack attribute, just try setting this to 1 even though the Delphi record you are converting doesn't indicate it.同样关于StructLayout Pack属性,即使您正在转换的 Delphi 记录没有指示它,也只需尝试将其设置为 1。 If I am missing something regarding Pack please correct me in the comment.如果我遗漏了有关Pack请在评论中纠正我。 Thanks谢谢

As for my final struct:至于我的最终结构:

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

The correctness of the code in the question depends entirely on what Char is.问题中代码的正确性完全取决于Char是什么。

  • In Delphi 2009 and later, Char is an alias to WideChar which is a 16 bit type.在 Delphi 2009 及更高版本中, CharWideChar的别名,它是一种 16 位类型。
  • In earlier versions, Char is an alias to AnsiChar which is a 8 bit type.在早期版本中, CharAnsiChar的别名, AnsiChar是 8 位类型。

So, your code is correct if you are using a version of Delphi earlier than Delphi 2009. Otherwise your C# code should replace CharSet.Ansi with CharSet.Unicode .因此,如果您使用的是早于 Delphi 2009 的 Delphi 版本,则您的代码是正确的。否则,您的 C# 代码应将CharSet.Ansi替换为CharSet.Unicode

The other difference is that the C# code insists on the array being null-terminated, whereas the Delphi code need not.另一个区别是 C# 代码坚持以空值结尾的数组,而 Delphi 代码则不需要。 So if your Delphi code wants to use all three elements as non-null values then you would need to avoid using a string on the C# side.因此,如果您的 Delphi 代码想要将所有三个元素都用作非空值,那么您需要避免在 C# 端使用string It would become:它会变成:

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

for pre-Unicode Delphi, or对于 Unicode 之前的 Delphi,或

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

for Unicode Delphi.对于 Unicode Delphi。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM