【问题标题】:How to parse C++ protobuf binary data by python protobuf?如何通过 python protobuf 解析 C++ protobuf 二进制数据?
【发布时间】:2016-08-31 16:29:36
【问题描述】:

我使用 C++ protobuf 将数据序列化为字符串。

/***** cpp code *****/
string serialized_data;
message_cpp.SerializeToString(&serialized_data);

问题:我可以在 python 中解析serialized_data 吗?以及如何?

我尝试了以下代码,但没有成功。

##### python code
message_python = foo.ParseFromString(serialized_data)
print message_python

但我得到None 作为print message_python 的输出。我也试过了

##### python code
message_python = foo.MergeFromString(serialized_data)
print message_python

但我得到了字符串serialized_data 的长度作为print message_python 的输出,即message_python == len(serialized_data)。这个结果与python protobuf API一致。

这是否意味着我无法在python中解析二进制数据,而这些数据是用C++序列化的?

更新:

我的目标:C++服务器总是生成图片流,图片发送到python服务器。

这是我的全部代码:

.proto 文件:

message MyImage{
    repeated int32 width = 1;
    repeated int32 height = 2;
    repeated bytes image = 3;
}

C++ 服务器:

zmq::context_t context(1);
zmq::socket_t socket(context, ZMQ_REP);
socket.bind("tcp://localhost:5555");

MyImage message_cpp;
// message_cpp.add_image(), add_width() and add_height() here.

string serialized_data;
message_cpp.SerializeToString(&serialized_data);
int counter = 3;
while (counter > 0) {
    zmq::message_t request;
    socket.recv(&request);
    std::string replyMessage = std::string(static_cast<char *>(request.data()),
                                           request.size());
    std::cout << "Recived from client: " + replyMessage << std::endl;
    sleep(1);
    zmq::message_t reply(serialized_data.size());
    memcpy((void*) reply.data(), serialized_data.data(), serialized_data.size());
    std::cout << "---length of message to client: " << 
                  reply.size() << std::endl;
    socket.send(reply);

    counter --;
}

python 客户端:

context = zmq.Context()
socket = context.socket(zmq.REQ)
port = "5555"
socket.connect("tcp://localhost:%s" %port)
print "Connecting to server..."
foo = my_image_pb2.MyImage()

for i in range(3):
    socket.send("hello from python")
    serialized_data = socket.recv()
    message_python = foo.ParseFromString(serialized_data)
    print "length of message from server:", len(serialized_data),"; type:", type(message)
    print "-----", message_python

这是结果:

服务器:

客户:

为什么fooNone,而不是一个类?关于如何修复它的任何想法?

【问题讨论】:

  • 嗯,protobuf 二进制数据是用哪种语言创建的并不重要。让那个透明是 protobuf 的唯一目的。 message_cpp.SerializeToString(&amp;serialized_data); 也不会产生 protobuf 二进制数据,而是如名字所说的字符串。
  • 您没有说通过什么方式将 serialized_data 从 C++ 传输到 Python。 (例如,将它们保存到 C++ 中的文件并在 Python 中加载。)您是否确认您获得了相同的数据?
  • 消息数据包含在'foo'中,ParseFromString后可以打印foo得到人类可读的实际消息数据。
  • 我更新了我的问题以明确:)
  • @πάνταῥεῖ 我更新了我的问题。我将数据序列化为字符串,因为提供给 zmq_send() 的数据的值类型是 string。但是客户端的结果似乎serialized_data不是一个常规字符串。

标签: python c++ protocol-buffers


【解决方案1】:

ParseFromString 解析它被调用的对象。它不返回任何东西。像这样使用它:

message = MyMessage()
message.ParseFromString(data)
print message

【讨论】:

  • 我刚刚更新了我的问题。如果我想在您的回答中从data 恢复我的图像信息,我该怎么办?
  • @DongLi 调用foo.ParseFromString() 后,您的数据现在在foo 中。您可以访问foo.widthfoo.heightfoo.imagefoo.ParseFromString() 不返回任何东西;它用消息内容填充foo
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
相关资源
最近更新 更多