反序列化Google Protobuf二进制文件

时间:2016-10-26 16:58:25

标签: python c++ parsing protocol-buffers binaryfiles

谷歌Protobuf比以往任何时候都更加困惑我,我正在努力了解事情的运作方式。

  1. 如果我理解正确,请帮助我理解。 .proto 文件定义消息的定义, protoc 是编译器。数据以二进制文件( .pb )编译。正确?如果没有,请你帮我理解。我无法处理Google Protobuf文档。这很令人困惑。并且没有与Stack Overflow或其他博客一起运气。

  2. 重要,我无法修改定义逻辑的C ++代码。话虽如此,我想反序列化 filename.pb (二进制文件)并通过Python解析结果。这可能吗?

  3. 提前感谢您的帮助!!

2 个答案:

答案 0 :(得分:3)

我不确定我是否回答你的问题,但我会给你一个例子。一旦有了Protocol_pb2.py,就可以使用protobuf python API(可能还有struct)轻松解析消息。我不是protobuf的专家,但我至少解析了Mumble消息。现在,我不知道你是如何使用protobuf以及为什么,但这个例子展示了如何解析mumble消息(使用protobuf),并希望能给你一些见解。所以:

导入protoc创建的protobuf文件(您按我回答上一个问题的方式创建它)&结构:

import struct
import Mumble_pb2 as mumble_protobuf

mumble_protobuf模块将包含转换为Python格式的.proto文件中定义的不同消息。您可以将不同的消息类型保存为例如dict:

PACKET_TYPES = {
    0: mumble_protobuf.Version,
    1: mumble_protobuf.UDPTunnel,
    2: mumble_protobuf.Authenticate,
...

我在这里跳过了一些东西,但是一旦收到数据包的二进制数据就可以解析它。我想每个应用程序都会以不同的方式执行操作,但是例如,mumble发送前缀为2个字节的protobuf消息,其中包含消息类型,以及4个字节,用于指示数据包长度。这可能在您的应用程序中有所不同。无论如何,你必须知道你要解析什么样的消息(假设你的协议有多种消息类型)。但作为一个例子:

# The header format corresponds to the mumble packet that send the prefix + protobuf-msg
HEADER_FORMAT = ">HI" # Big endian, unsigned short + unsigned int
packet_type, packet_length = struct.unpack_from(HEADER_FORMAT, buffer)

如果缓冲区中有多条消息,则需要根据数据包长度从缓冲区中提取数据包数据。当您知道消息类型时,您可以解析它。这部分只是从pb2文件中获取与消息类型对应的类,并根据它解析消息。

MessageClass = PACKET_TYPES[packet_type]
message = MessageClass()
message.ParseFromString(packet_data)

现在message最终将包含已解析的protobuf消息,您可以像构建它时一样使用它:您可以引用字段等:message.UserName或其他。

答案 1 :(得分:-2)

是的,您可以使用protoc生成的python代码对protobuf消息进行反序列化。 protoc编译器将以您的目标语言输出代码(在您的情况下为pythonC++)。

以下是一些可以提供帮助的资源:

  1. 在python中读写文件: https://docs.python.org/2/tutorial/inputoutput.html
  2. 协议缓冲消息的Python教程: https://developers.google.com/protocol-buffers/docs/pythontutorial