C++ 中的 Google 协议缓冲区:从现有结构创建消息

Posted

技术标签:

【中文标题】C++ 中的 Google 协议缓冲区:从现有结构创建消息【英文标题】:Google Protocol Buffers in C++: Creating a message from an existing struct 【发布时间】:2014-02-26 17:07:25 【问题描述】:

我正在考虑将 Google protocol buffers 作为我使用命名管道在 C++ 和 C# 之间进行通信的问题的解决方案。但我有一个担忧:我在 protobuf 上所能找到的只是如何使用 protobuf 编译器从原型创建消息。这很简洁,但我还需要能够序列化现有结构。我似乎找不到任何信息(但也许我忽略了它)。你知道是否可以使用 protobufs 在 C++ 中序列化一个结构,以便可以在 .NET 中读取它,而无需修改所述现有结构?

【问题讨论】:

不,这不可能,您必须映射数据。 这太糟糕了。你能推荐任何替代系统吗? @πάνταῥεῖ 没有什么是不可能的。不在 C++ 中。 Protobuf 具有非常简单的编码格式,并且易于处理。编写代码以序列化为该格式非常容易,但它反转了很难的经典 protobuf 工作流程(正常工作流程:编写 .proto 消息,为其生成 C++ 结构;反向工作流程:编写具有序列化的 C++ 结构例程,生成 .proto 消息/原型)。但同样,并非不可能。 【参考方案1】:

是的,不是的。

这是可能的。事实上,我已经做到了。不是 .NET 加载部分,而是对 protobuf 的序列化以及从 C++ 类生成原型。但是,这样做需要做很多事情,并不是那么容易。

首先,protobuf 表示数据的能力非常有限。它们基本上只能表示 POD 类型(在 C++ 意义上),几乎没有其他能力。我个人不得不在格式中添加一些基本的东西,以使其成为适当的全功能序列化格式。但是,如果您将自己限制为 POD 类型,那么普通的 protobuf 格式就可以正常工作。

第二件事是您需要某种序列化库,这将要求您为每个结构/类添加一些代码来执行序列化/反序列化(不一定是“侵入式”,这意味着您可能不必更改类,只需在旁边添加一些代码)。您可以查看Boost.Serialization,这是如何在 C++ 中创建序列化库的基本模板。 Boost.Serialization 对于这个目的不是特别灵活,因此,您可能需要更改一些东西(就像我必须做的那样)。

第三件事是,您将需要相当多的幕后技巧才能实现这一目标。特别是,您将需要一个可靠且功能丰富的运行时类型识别系统 (RTTI),以便能够拥有有用的类型名称,并且您可能需要巧妙的元编程或一些侵入性的类层次结构才能能够检测需要为其生成原型的用户定义类型。

所以,这就是为什么我的回答是“是和否”,因为这是可能的,但并非没有大量工作和一个可以依赖的良好框架。

注意:编写代码以将数据编码/解码为 proto-buf 格式(使用那些小整数等)确实很容易,proto-buf 格式如此简单,几乎可笑。编写序列化框架,让您可以做一些花哨的事情,比如生成原型,这是困难的部分。

【讨论】:

感谢您的详细回复。我认为将数据映射到生成的消息会更简单,因为我正在使用的结构数量相当有限,但非常感谢详细的回答。我相信它将来会派上用场! @Ben 是的,使用普通的 proto-buf 工作流程可能更容易。我在做我所描述的事情时遇到麻烦的唯一原因是因为我已经有了所有的机制(序列化/ RTTI),而且只实现编码和原型的生成(.proto 文件)是一件小事.但如果没有这些机制,可能不值得付出努力。

以上是关于C++ 中的 Google 协议缓冲区:从现有结构创建消息的主要内容,如果未能解决你的问题,请参考以下文章

从 Google 协议缓冲区中的重复字符串(列表)中删除一个随机值

用于 Spanner API 的协议缓冲区

Windows 上的 Thrift / Google 协议缓冲区

使用 Google 协议生成 C# 文件失败

反序列化协议缓冲区c ++中的字符串数组

协议缓冲区中的多态性 3