【问题标题】:Reading serialized C++ structs in C# using BinaryReader使用 BinaryReader 在 C# 中读取序列化的 C++ 结构
【发布时间】:2012-03-27 07:24:56
【问题描述】:

我有一些文件已通过使用二进制 fstream 直接编写 C++ structs 进行序列化。现在,当我为相应的 C# 类生成读取方法时,我发现这些方法并不是真正的一对一映射,可能是因为结构打包。

所以我的问题是 - 处理这种情况的最佳方法是什么?我有 C++ 和 C# 源代码,所以我可以更改任何一部分。我应该尝试在不打包的情况下序列化 C++(我假设这是使用 #pragma pack(1) 完成的,对)还是以某种方式调整我的 C# 代码以考虑到这些差距?

还是反序列化的问题完全不同,与打包无关?

更新 1 我发现 C++ enums 有 4 个字节长,bool 值有 2 个字节长(谁知道?),但即使添加了 #pragma pack(1) 我也只能正确读取第一条记录。另外,我检查了sizeof(MyStructure) 的字节数,并且值匹配。这一定意味着记录之间有一些填充。

Update 2该死,在代码中发现了一个错误。复制粘贴错误。需要 PVS Studio 什么的。现在一切都好。 (是的,布尔值是 1 个字节大。)

【问题讨论】:

  • 枚举不一定是 4 个字节,bool 不一定是 2 个字节。这取决于您的平台和编译器。 (我知道这在这里没有帮助,但我需要指出这一点,以免其他人从阅读本文中得到错误的想法)。

标签: c# c++ serialization struct packing


【解决方案1】:

对齐是问题的可能原因。

结构打包/字节对齐取决于编译器实现,并且还随构建目标而变化,以针对相关硬件进行优化。这意味着明智的做法是不要依赖编译器为给定构建生成的一组给定的结构对齐。

如果您需要可靠地共享结构,最好#pragma pack(1) 并在性能问题时手动添加填充。只有在结构紧凑的内部循环中使用时,这才可能是一个问题。

手动对齐示例:

struct Record {
    char c;
    char __padding[7];
    double d;
};

您的 C# 代码将如下所示:

this.c = reader.ReadChar();
reader.ReadBytes(7); // or reader.BaseStream.Seek(7, SeekOrigin.Current);
this.d = reader.ReadDouble();

【讨论】:

  • 实际上,事实证明,它不仅仅是打包,还有变量的大小。谁知道bool的值占了2个字节?
猜你喜欢
  • 1970-01-01
  • 2020-12-31
  • 1970-01-01
  • 2011-04-25
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 2021-03-29
  • 1970-01-01
相关资源
最近更新 更多