[英]Protobuf-net is incompatible with official google Protobuf for C++ (message encoding)
We had some (lots of) classes in .NET. .NET中有一些(很多)类。 We used protobuf-net to mark them up, and generate .proto wrappers for C++ code side via google original library .
我们使用protobuf-net对其进行了标记,并通过google原始库为C ++代码端生成了.proto包装器。
So I have a message (C++ DebugString() on some EventBase class (in .NET EventCharacterMoved
inherits EventBase
while in C++ I just write to optional property)): 因此,我收到一条消息(某些EventBase类上的C ++ DebugString()(在.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
}
}
}
(From such .proto file) (来自.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];
}
In C++ I send this and we send the same message contents from .NET. 在C ++中,我发送此消息,然后从.NET发送相同的消息内容。
The C++ code can parse C++ encoded message as well as the .NET encoded one. C ++代码可以解析C ++编码的消息以及.NET编码的消息。 The .NET code can only parse the .NET message.
.NET代码只能解析.NET消息。
Over the wire we get 87 bytes flying (same size from .Net file and C++ file ) yet contents are different: 通过电线,我们获得了87个字节的飞行空间( .Net文件和C ++文件的大小相同),但内容有所不同:
As you can see its similar yet not same. 如您所见,其相似之处并不相同。 As a result of such difference CPP code can read .NET C# messages while .NET can not read CPP messages .
由于这种差异, CPP代码可以读取.NET C#消息,而.NET无法读取CPP消息 。
In code on deserialization we get: 在反序列化代码中,我们得到:
An unhandled exception of type 'System.InvalidCastException' occurred in TestProto.exe
TestProto.exe中发生了'System.InvalidCastException'类型的未处理异常
Additional information: Unable to cast object of type 'TestProto.EventBase' to type 'TestProto.EventCharacterMoved'.
附加信息:无法将类型为“ TestProto.EventBase”的对象转换为类型为“ TestProto.EventCharacterMoved”。
in code like: 在像这样的代码中:
using (var inputStream = File.Open(@"./cpp_in.bin", FileMode.Open, FileAccess.Read)) {
var ecm = Serializer.Deserialize<EventCharacterMoved>(inputStream);
}
Let's look at (as mentioned by jpa in his comment) protoc --decode_raw
option: 让我们看一下(如jpa在他的评论中提到的)
protoc --decode_raw
选项:
This can be related to the fact that my CPP wrapper uses latest google protobuf version while protobuf-net probably uses some older encoding format or something like this... 这可能与以下事实有关:我的CPP包装器使用了最新的Google protobuf版本,而protobuf-net可能使用了一些较旧的编码格式或类似的格式...
So I wonder how to make .NET protobuf read C++ messages (make tham capable of decoding same stuff)? 因此,我想知道如何使.NET protobuf读取C ++消息(使tham能够解码相同内容)?
Or at least how to make original google protobuf encode same way .NET protobuf does? 或者至少如何使原始的Google protobuf编码与.NET protobuf相同?
And for those who are really interested and would like to get into it zipped bundle with simplified example (VS 2010 solutions for C++ and C# code included) 对于那些真正感兴趣并希望通过简化示例进入压缩包的用户(包括适用于C ++和C#代码的VS 2010解决方案)
Edit; 编辑; this should be fixed in r616 and above.
该问题应在r616及更高版本中修复。
I've finally had chance to look at this (apologies for delay, but social seasonal holiday demands intervened). 我终于有机会研究一下(为延迟而道歉,但社交季节性假期需求有所干预)。 I understand what is happening now.
我了解现在发生了什么。
Basically, the data is theoretically identical; 基本上,数据在理论上是相同的; what this actually comes down to is field-ordering.
这实际上归结为现场排序。 Technically, fields are usually written in ascending order, but can be expected in any order.
从技术上讲,字段通常按升序编写,但可以按任何顺序期望。 With regards to protobuf-net;
关于protobuf网; for types that don't involve inheritance it will work fine regardless of order.
对于不涉及继承的类型,无论顺序如何,它都可以正常工作。 The protobuf specification does not define inheritance, so protobuf-net adds support for that (due to constant demand) additionally to the specification.
protobuf规范没有定义继承,因此protobuf-net在规范的基础上(由于不断的需求) 增加了对该继承的支持。 As an implementation feature, it writes the sub-class information first (ie field 15, the sub-type, is written ahead of field 10).
作为一种实施的功能时,它首先写入(即字段15,子类型,则提前写入字段10)的子类的信息。 At the current time, during deserialization it also expects the sub-type information first.
当前,在反序列化期间,它也首先需要子类型信息。 This has rarely impacted anyone, because since protobuf-net is the only implementation that uses inheritance like this, use of the inheritance feature is mostly only seen with protobuf-net to protobuf-net usage.
这几乎对任何人都没有影响,因为既然protobuf-net是唯一这样使用继承的实现,那么继承功能的使用通常仅在protobuf-net到protobuf-net的使用中才能看到。
In your case, you're using .proto to interop with CPP; 就您而言,您正在使用.proto与CPP互操作; which means the CPP code will be able to consume to protobuf-net data, but it may have a type-cast exception going the other way (basically, it starts constructing the concrete type at the time it gets the first data field).
这意味着CPP代码将能够使用protobuf-net数据,但是它可能会有类型转换异常(反之亦然)(基本上,它在获取第一个数据字段时便开始构造具体类型)。
Despite rarely being an issue, this is something that needs fixing. 尽管很少有问题,但这是需要解决的问题。 I can try to look at this later today or tomorrow.
我可以尝试今天晚些时候或明天看看。
Options: 选项:
EventBase
with just the EventCharacterMoved
data first, and serialize; EventBase
只编写带有EventCharacterMoved
数据的EventBase
,然后进行序列化; now in a separate model write an EventBase
with just the TreeFloat
data, and serialize; TreeFloat
数据编写一个EventBase
并进行序列化; this will simulate writing them in the required order (protobuf streams are appendable) - not pretty This looks pretty similar to the problems noted in http://code.google.com/p/protobuf-net/issues/detail?id=299 and http://code.google.com/p/protobuf-net/issues/detail?id=331 which were allegedly fixed by http://code.google.com/p/protobuf-net/source/detail?r=595 这看起来与http://code.google.com/p/protobuf-net/issues/detail?id=299和http://code.google.com/p/protobuf-net/issues中指出的问题非常相似/ detail?id = 331 ,据称由http://code.google.com/p/protobuf-net/source/detail?r=595修复。
Is the version of .NET protobuf you're using new enough to have incorporated that fix? 您使用的.NET protobuf版本是否足够新,可以合并该修复程序?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.