c# - 使用 BinaryReader 在 C# 中读取序列化的 C++ 结构

标签 c# c++ serialization struct packing

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

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

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

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

更新 2 该死,在代码中发现了一个错误。复制粘贴错误。需要 PVS Studio 什么的。现在一切都好。 (是的, bool 值有 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();

关于c# - 使用 BinaryReader 在 C# 中读取序列化的 C++ 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9885025/

相关文章:

c# - 如何在我的模块中使用 BinaryConnection 发送和接收数据

c# - 比较使用 PropertyInfo.GetValue() 检索的值时出现意外结果

c++ - 指向外部类 C++

java - 使用 Jackson 将递归对象序列化到一定深度

ruby-on-rails-3 - 如何在 rspec 中使用 current_user 进行序列化器测试

jquery - 将记录转换为序列化表单数据以通过 HTTP 发送

c# - 当变量更改时生成事件以从代码类发送以形成类 c#

c# - PageAsyncTask 时间与顺序进程相同吗?

c# - 串行 COM 端口超时设置

c++ - sqlite C\C++ 库是否将 DB 文件保存为内存映射文件?有可能让它这样做吗?