LINUX.ORG.RU

отправить необработанные байты в string-e из protobuf (C++)

 ,


0

1

Привет, всем!

Имеется вектор с сырыми данными

std::vector<uchar> bu;

Пытаюсь записать в поле типа string из proto3

message MyData
{
   // ...
   string image = 18;
   // ...
}

в виде std строки:

std::string((char*)bu.data(), bu.size());

получаю ошибку

[libprotobuf ERROR google/protobuf/wire_format_lite.cc:577] String field 'myservice.getMyData.image' contains invalid UTF-8 data when serializing a protocol buffer. Use the 'bytes' type if you intend to send raw bytes. 

Попытка засунуть в протобуфер сразу std::vector<uchar> закончилась на стадии компиляции

note:   no known conversion for argument 1 from ‘std::vector<unsigned char>’ to ‘const string& {aka const std::__cxx11::basic_string<char>&}’

Как правильно заполнить string из protobuf?

Ответ на: комментарий от dhampire

string->bytes поможет

у меня изначально bytes по сути - это std::vector. И если я пишу прямо этот вектор в поле протобуфера - то получаю ошибку компиляции

Попытка засунуть в протобуфер сразу std::vector >>закончилась на стадии компиляции

note: no known conversion for argument 1 from >>‘std::vector’ to ‘const string& {aka const >>std::__cxx11::basic_string&}’

cppprogger ()

Ну а если так сделать.

message MyData
{
   // ...
   bytes image = 18;
   // ...
}

Проблема с строкой в том что он ждет от тебя const string&,а не std::vector<unsigned char>

anonymous ()
Ответ на: комментарий от invy

Изначально пробовал использовать байты (может здесь я ошибаюсь, принимая за байт unsigned char) т.е. взял сырые данные в виде

std::vector<uchar> bu;

в протобуфе взял тоже поле bytes

message MyData
{
   // ...
   bytes image = 18;
//...

в итоге получил

error: no matching function for call to ‘::set_image(std::vector<unsigned char>&)’
                                      
 note:   no known conversion for argument 1 from ‘std::vector<unsigned char>’ to ‘const string& {aka const std::__cxx11::basic_string<char>&}’
потому и стал со стоками «мутить»

cppprogger ()
Последнее исправление: cppprogger (всего исправлений: 1)
Ответ на: комментарий от cppprogger
//sender

std::vector<uchar> v;
MyData msg;

msg.set_image((char*)v.data(), v.size()*sizeof(uchar));

std::string wire;
bool serialized = msg.SerializeToString(&wire);

//reciever
std::vector<uchar> inV;
std::string wire;
MyData msg;
bool decoded = msg.ParseFromString(wire);
if (decoded && msg.has_image()) {
  inV.resize(msg.image().size());
  memcpy(inV.data(), msg.image().data(), inV.size());
}

очень сложный код...

dhampire ★★★ ()
Ответ на: комментарий от dhampire

Спасибо, большое! Код не сложный, но очень хочеться понимать.

А что делает метод SerializeToString? Он эквивалентен вызову конструктора string(), как ниже?

У меня, почему-то, вот так проскочило для bytes image:

//sender
MyData msg;
std::vector<uchar> v;
image = std::string((char*)v.data(), v.size());
msg.set_image(&image[0], image.size());

//reciever
std::string image = response.image();
std::vector<char> tmp(image.begin(), image.end());
// далее каждый char при обработке рассматриваю как uchar
Логика такая. Я как бы uchar (целое беззнаковое) формально интерпретирую как char* (знаковое), но при этом все это храниться в поле bytes и методы протобуф не пытаются извлечь из char* симовлы. А вот, если бы эти символы хранились в строке, то протобуф бы пытался их интерпретировать как символы и падал с ошибкой " String field 'myservice.getMyData.image' contains invalid UTF-8 data when serializing a protocol buffer.".

А что же тогда делает сериализация? в каком формате кодируется? Что внутри обратного преобразования ParseFromString()?

cppprogger ()