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