当前位置: 首页 > 知识库问答 >
问题:

Protobuf-net与官方的google Protobuf for C++(消息编码)不兼容

叶茂
2023-03-14

我们在.NET中有一些(很多)类。我们使用protobuf-net对它们进行标记,并通过google original库为C++代码端生成。proto包装器。

因此,我在某个EventBase类上有一条消息(C++DebugString()(.NETEventCharacterMoveinheritsEventBase,而在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];
}

正如你所看到的,它相似但不相同。由于这种差异,CPP代码可以读取。NET C#消息,而。NET不能读取CPP消息。

在反序列化的代码中,我们得到:

TestProto.exe中出现类型为“System.InvalidCastException”的未处理异常

using (var inputStream = File.Open(@"./cpp_in.bin", FileMode.Open, FileAccess.Read)) {
    var ecm = Serializer.Deserialize<EventCharacterMoved>(inputStream);
}

或者至少如何使原始google protobuf的编码方式与.NET protobuf相同?

对于那些真正感兴趣并想进入它的人来说,带有简化示例的压缩包(包括C++和C#代码的VS2010解决方案)

共有1个答案

朱浩大
2023-03-14

基本上,数据在理论上是相同的;这实际上归结为字段排序。从技术上讲,字段通常是按升序编写的,但可以期望以任何顺序编写。关于Protobuf-net;对于不涉及继承的类型,无论顺序如何,它都可以正常工作。protobuf规范没有定义继承,因此protobuf-net在规范中添加了对继承的支持(由于不断的需求)。作为实现特性,它首先写入子类信息(即,字段15,子类型,写在字段10之前)。在当前时间,在反序列化过程中,它也首先期望子类型信息。这很少影响到任何人,因为protobuf-net是唯一使用这种继承的实现,所以继承特性的使用大多只在protobuf-net到protobuf-net之间使用。

在您的例子中,您使用。Proto与CPP进行互操作;这意味着CPP代码将能够使用protobuf-net数据,但它可能会出现另一种类型转换异常(基本上,它在获得第一个数据字段时开始构造具体类型)。

尽管这很少成为一个问题,但这是需要解决的问题。我可以试着今天晚些时候或者明天再看这个。

  • 确保子类型字段始终低于任何数据字段
  • 如果您知道它需要子类型,请使用合并API,并传入所需类型的现有新对象-这将正确填充现有对象
  • 等待一两天(希望!) 使用版本r616或更高版本以获得正确的修复
  • 使用interop时避免继承(和其他特定于实现的特性)
    • 注意您可以通过封装对相同的数据进行建模而不需要继承--而且它会很好地工作;这里的问题是具体类型的创建
    • 首先使用EventCharacterMoved数据编写EventBase,然后序列化;现在,在一个单独的模型中,只使用Treefloat数据编写EventBase,并进行序列化;这将模拟按照所需的顺序编写它们(protobuf流是可附加的)-不太好

 类似资料:
  • 当使用Google Protocol Buffers Version3.0.0(发行版)时,maven编译以下生成的java-class会导致编译器错误: 这只是生成的类之一,所有类的maven错误都是一样的,如下所示: 这些类包含在工作的Maven-Tycho-Build配置中,其类路径上有protobuf-java-3.0.0.jar。在Eclipse中编译代码时,它没有编译器错误。 此外,当

  • 我知道这个问题。 由于其高效的编码、显式模式和广泛的支持,我正在考虑将原型3用于文件格式。然而,模式中非常不方便的一部分是它不允许必填字段。 谷歌有理由删除Protobuf 3中的必填字段。他们遇到的问题是真实的(删除必填字段是一个突破性的改变),但他们的解决方案是胡说八道。 无论如何,我的问题是:Protobuf 3允许您为字段添加自定义选项。是否有人使用该方法(或其他方法)向Protobuf

  • 我正在尝试升级到使用protobuf版本3,并与版本2保持向后兼容。除了一件事之外,它似乎可以工作——在proto-2中,您可以设置自己的默认值,但在proto 3中,您不能。如果您在proto-2中选择的默认值不是proto-3中的标准默认值,那么您就有问题了。例如,在proto-2中: 现在在proto-3中必须: 在proto-2和proto-3中,丢失的值不会在消息中发送。但是proto-

  • 官方        LSV官方网站包含了公司的产品、服务介绍以及SDK开发包的提供,用户可以进入官网下载产品免费使用,也可对相关产品服务进行了解。 点击链接了解详情 QQ群        LSV的用户交流群,LSV的用户群体几乎涵盖GIS的各个行业,同时开设了不同行业的行业交流群,方便大家交流和技术探讨。 公众号        LSV拥有自己的公众号,发布LSV相关的资讯、教程以及相关应用方案,用

  • 我在编写一个简单的Minecraft 1.10测试插件时,在EclipseJavaMars上收到以下错误:“无法从Command dSender类型对非静态方法sendMessage(String)进行静态引用。”除了主类之外,这是一个单独的命令类。这是整个类:

  • 这是我的java程序:

  • 我想将protobuf序列化消息转换为人类可读的JSON格式。我面临的主要问题是,我需要这样做,而无需事先将proto描述符编译成Go代码。我有权访问 来自

  • 我一直在尝试将. net核心库项目引用到我的Azure函数项目中,以调用. net核心类库中定义的进程之一。 net核心库项目使用ILogger。 但是,每当我尝试运行一个函数时,我都会收到以下错误: [2019/11/29 1:08:35 上午]“Function1”函数出错:Microsoft.Azure.WebJobs.Host:错误索引方法“Function1”。Microsoft.Azu