【发布时间】:2012-12-24 10:46:26
【问题描述】:
我们在 .NET 中有一些(很多)类。我们使用protobuf-net 标记它们,并通过google original library 为C++ 代码端生成.proto 包装器。
所以我有一条消息(C++ DebugString() 在某个 EventBase 类上(在 .NET 中 EventCharacterMoved 继承 EventBase 而在 C++ 中我只是写入可选属性):
UserId: -2792
EventCharacterMoved {
Coordinates {
Position {
X: 196.41913
Y: 130
Z: 213
}
Rotation {
X: 207
Y: 130
Z: 213
}
}
OldCoordinates {
Position {
X: 196.41913
Y: 130
Z: 213
}
Rotation {
X: 207
Y: 130
Z: 213
}
}
}
(来自这样的 .proto 文件)
message Coordinates {
optional TreeFloat Position = 1;
optional TreeFloat Rotation = 2;
}
message EventBase {
optional int32 UserId = 10 [default = 0];
// the following represent sub-types; at most 1 should have a value
optional EventCharacterMoved EventCharacterMoved = 15;
}
message EventCharacterMoved {
optional Coordinates Coordinates = 100;
optional Coordinates OldCoordinates = 101;
}
message TreeFloat {
optional float X = 1 [default = 0];
optional float Y = 2 [default = 0];
optional float Z = 3 [default = 0];
}
在 C++ 中,我发送这个,我们从 .NET 发送相同的消息内容。
C++ 代码可以解析 C++ 编码的消息以及 .NET 编码的消息。 .NET 代码只能解析 .NET 消息。
通过网络我们得到 87 个字节(与 .Net file 和 C++ file 大小相同)但内容不同:
正如您所见,它相似但又不一样。 由于这种差异,CPP 代码可以读取 .NET C# 消息,而 .NET 无法读取 CPP 消息。
在反序列化的代码中我们得到:
发生了“System.InvalidCastException”类型的未处理异常 在TestProto.exe中
附加信息:无法转换类型的对象 'TestProto.EventBase' 输入 'TestProto.EventCharacterMoved'。
在代码中:
using (var inputStream = File.Open(@"./cpp_in.bin", FileMode.Open, FileAccess.Read)) {
var ecm = Serializer.Deserialize<EventCharacterMoved>(inputStream);
}
让我们看看(正如jpa 在他的评论中提到的)protoc --decode_raw 选项:
这可能与我的 CPP 包装器使用最新的 google protobuf 版本有关,而 protobuf-net 可能使用一些较旧的编码格式或类似的东西......
所以我想知道如何让 .NET protobuf 读取 C++ 消息(让 tham 能够解码相同的东西)?
或者至少如何使原始 google protobuf 以与 .NET protobuf 相同的方式编码?
对于那些真正感兴趣并想参与其中的人zipped bundle with simplified example (VS 2010 solutions for C++ and C# code included)
【问题讨论】:
-
能否请您出示您用于c++版本的.proto,以及c#中使用的合同。它们应该完全兼容,如果它们不兼容,我会感到非常惊讶。我没有手动处理这 2 个二进制片段(不是在 PC 上,如果我今天启动 PC,我会被妻子谋杀),但发布使用的合同会对我有很大帮助。此外,protobuf 并不要求保证字段顺序(多个不同的文件可以包含相同的数据)——尽管实际上它通常是按升序编写的。
-
另外,让我知道mention的继承是否是protobuf定义的一部分 - 意思是:EventBase也是合同。
-
提供示例,简化原始代码。
-
通过
protoc --decode_raw同时运行net_in.bin和cpp_in.bin,我看到唯一的区别是字段10(UserId)是先写还是最后写。 C++ 首先发出它,.NET 出于某种原因最后发出(通常它们应该按标签按数字顺序排列)。但不确定是什么导致了实际问题。 -
我的行动方案(如果我现在有时间的话)将检查 ProtoBuf.net 的源并确保它以正确的顺序编码标签。
标签: c# c++ .net protocol-buffers protobuf-net