Qt + protobuf, типы?

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

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

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

Ответы

Ответ 1

Создание 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;
}

Ответ 2

Вместо:

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

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

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

РЕДАКТИРОВАТЬ: выше двух дает тот же результат, но я не уверен, что это правильно. Кажется, что это работает лучше:

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

EDIT2: ОК, теперь я знаю, как это работает: первые два пути неправильны, если в сериализации есть \0 char - все после этого оно затем теряется. Чтобы исправить это, можно написать:

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

Ответ 3

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

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

Здесь вы можете найти хорошее объяснение В protobuf-c, необязательная переменная uint32 имеет значение 0

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

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

Ответ 4

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

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())
        {
            //...
        }
    }
}