2010-11-23 19 views
14

Me gustaría profundizar en los búferes de protocolo de Google en el desarrollo de Qt, pero estoy teniendo problemas para descubrir cómo incorporarlos mejor.Qt + protobuf, tipos?

En última instancia, quiero enviar con QUdpSocket y QTcpSocket utilizando búferes de protocolo.

¿Cuál es el mejor método para pasar de una memoria intermedia de protocolo message al envío de datos a través de una toma de corriente (QByteArray) y luego de vuelta al otro lado?

Respuesta

12

Creación de una QByteArray de un objeto 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); 

lectura posterior protobuf un objeto desde un QByteArray:

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

No está mal per se, pero necesita identificar el mensaje de alguna manera e en el otro lado. Además, necesita identificar la longitud de los datos. Protobuf no hace internamente ninguna de esas cosas. Además, la versión de salida de flujo es la más lenta de las formateadoras - las salidas vector/array son más rápidas. –

+0

He estado tratando de usar el método 'SerializeToArray', pero no puedo averiguar cómo hacer la conversión a' QByteArray'. ¿Podría dar un ejemplo de eso? – Jay

+0

Consulte a continuación el código formateado: no sé cómo formatear el código en los comentarios. Lo siento por eso. \ n \ n void convertQByteArrayToUser (QByteArray & aByteArray) { com :: su :: nombre_espacio :: Usuario usuario; if (! User.ParseFromArray (aByteArray.data(), aByteArray.size())) {// no pudo analizar } else { // yayyyyy si (user.has_userid()) { // ... } } } – Viren

3

@ James: Se puede utilizar ParseFromArray(), por ejemplo, de la siguiente manera: (Tenga en cuenta que ParseFromArray() está disponible solo en versiones de proto-buf-lite de las 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()) 
     { 
      //... 
     } 
    } 
} 
+0

Downvote debido a la declaración incorrecta: ** disponible solo en la versión de proto-buf-lite de las libs **. Me llevó dos horas descubrir que también está disponible en la versión completa. Quitar la [Documentación de la API de Google Light] (https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message_lite#classes-in-this-file): 'Esta interfaz está implementada por todos los objetos de mensaje de protocolo. Los mensajes no litera implementan además la interfaz del mensaje, que es una subclase de MessageLite' – SebNag

6

En lugar de:

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

también se puede escribir:

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

EDIT: Por encima de dos da el mismo resultado, pero no estoy seguro de carnero que es correcta. Éste parece funcionar mejor:

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

Edit2: OK, ahora sé como funciona: dos primeras formas son incorrectas si hay \ 0 caracter en la serialización - todo después de que se perdió entonces. Para corregirlo se puede escribir:

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

con el siguiente código es realmente peligroso

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

puede encontrar una buena explicación aquí In protobuf-c, can optional uint32 variable have value 0

una manera correcta para crear un QByteArray de un protobuf el mensaje es

QByteArray byteArray; 
byteArray.resize(message.ByteSize()); 
message.SerializeToArray(byteArray.data(), byteArray.size()); 
Cuestiones relacionadas