2010-11-23 2 views
14

Я хотел бы окунуться в буферы протокола Google в разработке Qt, но мне трудно понять, как их лучше всего включить.Qt + protobuf, типы?

В конечном счете, я хочу отправить QUdpSocket и QTcpSocket с использованием протокольных буферов.

Каков наилучший способ перехода между протокольным буфером message на отправку данных через сокет (QByteArray), а затем обратно с другой стороны?

ответ

12

Создание QByteArray из Protobuf объекта:

Person person; // a protobuf object 
person.set_id(123); 
person.set_name("Bob"); 
person.set_email("[email protected]"); 

std::ostringstream out; 
person.SerializeToOstream(&out); 
QByteArray byteArray(out.str().c_str()); 
sendSerializedPersonOverQTcpSocket(byteArray); 

Чтение назад объект Protobuf из QByteArray:

QByteArray byteArray = readSerializedPersonFromQTcpSocket(); 
Person person; 
if (!person.ParseFromArray(byteArray, byteArray.size())) { 
    std::cerr << "Failed to parse person.pb." << std::endl; 
} 
+4

Неправильно, но вам нужно каким-то образом определить почтовый ящик с другой стороны. Кроме того, вам необходимо определить длину данных. Протобуф не делает внутренне ни одну из этих вещей. Кроме того, версия выходного потока - самая медленная из форматов: выходные/векторные выходы быстрее. – 2010-11-23 07:15:15

+0

Я пытался использовать метод SerializeToArray, но не могу понять, как сделать преобразование в `QByteArray`. Не могли бы вы привести пример? – Jay 2010-11-23 15:30:39

3

@James: Вы можете использовать ParseFromArray(), например, как показано ниже: (Обратите внимание, что ParseFromArray() доступен только на прото-buf-lite версиях libs).

void convertQByteArrayToUser(QByteArray& aByteArray) 
{ 
    com::your::name_space::User user; 
    if(!user.ParseFromArray(aByteArray.data(), aByteArray.size())) 
    { 
     //could not parse 
    } 
    else { //yayyyyy    
     if(user.has_userid()) 
     { 
      //... 
     } 
    } 
} 
6

Вместо:

std::ostringstream out; 
person.SerializeToOstream(&out); 
QByteArray byteArray(out.str().c_str()); 

вы также можете написать:

QByteArray byteArray(person.SerializeAsString().c_str()); 

EDIT: Выше два дает тот же результат, но я не уверен, что кастрированный баран это правильно. Это, кажется, работает лучше:

QByteArray byteArray(QString::fromStdString(person.SerializeAsString())); 

edit2: Хорошо, теперь я знаю, как это работает: первые два способа не правы, если есть \ 0 символ в сериализации - все после этого он потом потерял. Чтобы это исправить, можно написать:

QByteArray byteArray(person.SerializeAsString().c_str(), person.ByteSize()); 
4

Используя приведенный ниже код действительно опасно

std::ostringstream out; 
person.SerializeToOstream(&out); 
QByteArray byteArray(out.str().c_str()); 
sendSerializedPersonOverQTcpSocket(byteArray); 

Вы можете найти хорошее объяснение здесь, In protobuf-c, can optional uint32 variable have value 0

правильный способ создания QByteArray из Protobuf сообщение

QByteArray byteArray; 
byteArray.resize(message.ByteSize()); 
message.SerializeToArray(byteArray.data(), byteArray.size()); 
Смежные вопросы