Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse C++ protobuf binary data by python protobuf?

I use C++ protobuf to serialize data to string.

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

Question: can I parse serialized_data in python? and how?

I've tried the following code, but it did not work.

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

But I get None as the output of print message_python. I've also tried

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

But I get the length of string serialized_data as the output of print message_python, i.e. message_python == len(serialized_data). This result agrees with python protobuf API.

Does this means that I cannot parse the binary data in python, which are serialized in C++?

Update:

My goal: C++ server always generates image stream and image is sent to a python server.

Here are my whole codes:

.proto file:

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

C++ server:

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 client:

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

This is the result:

server:

server

client:

client

Why the foo is None, not a class? Any idea about how to fix it?

like image 455
Dong Li Avatar asked Aug 31 '16 16:08

Dong Li


1 Answers

ParseFromString parses into the object it is called on. It doesn't return anything. Use it like:

message = MyMessage()
message.ParseFromString(data)
print message
like image 139
Kenton Varda Avatar answered Sep 28 '22 02:09

Kenton Varda