я использую MsgPack
как часть пользовательского бэк-энда, который я создаю для SOCI
API доступа к базе данных C ++. Изначально некоторые из моих SOCI
классы были MsgPack::sbuffer
объекты как переменные-члены, но я столкнулся с некоторыми проблемами в деструкторе моего SOCI
объект — я считаю, что проблема связана с тем, как SOCI
ссылка подсчитывает некоторые из его объектов и памяти, которая лежит в основе MsgPack
объект освобождается несколько раз.
В попытке решить эту проблему, я решил заменить MsgPack::sbuffer
переменные-члены с std::vector<char>
переменные-члены, и использовать их для заполнения MsgPack::sbuffer
с помощью pack_raw_body
метод. К сожалению, у меня тоже проблемы с этим.
Пожалуйста, рассмотрите следующий (псевдо-) фрагмент кода …
msgpack::sbuffer buf1;
msgpack::packer<msgpack::sbuffer> bufPkr1(&buf1);
bufPkr1.pack_array(num);
for (int ndx = 0; ndx < num; ++ndx) {
bufPkr1.pack_array(3);
bufPkr1.pack(std::string("foo"));
bufPkr1.pack(std::string("bar"));
bufPrk1.pack(221);
}
std::vector<char> chrVct = std::vector<char>(buf1.size(), *buf1.data());
msgpack::unpacked unPkd1;
msgpack::unpack(&unPkd1, buf1.data(), buf1.size());
msgpack::object toStr1 = unPkd1.get();
std::cout << "MsgPack1: " << toStr1 << std::endl;
msgpack::sbuffer buf2;
msgpack::packer<msgpack::sbuffer> bufPkr2(&buf2);
bufPkr1.pack_raw(chrVct.size());
bufPkr1.pack_raw_body(chrVct.data(), chrVct.size());
msgpack::unpacked unPkd2;
msgpack::unpack(&unPkd2, buf2.data(), buf2.size());
msgpack::object toStr2 = unPkd2.get();
std::cout << "MsgPack2: " << toStr2 << std::endl;
Выход…
MsgPack1: [["foo", "bar", 221], ["foo", "bar", 221], ["foo", "bar", 221],..., ["foo", "bar", 221]]
MsgPack2: ""
В общем, мне просто трудно понять, как работать с объектами MsgPack, и я нахожу документацию / примеры немного скудными. Любая помощь, которую могут предложить люди, будет высоко ценится!
Одна из особенностей API MsgPack, похоже, связана с временем жизни различных объектов MsgPack, а также с объектами / целочисленными типами данных, которые упаковываются. в объекты MsgPack.
Код выше наверное работал бы лучше, если бы я следовал этой идиоме …
msgpack::sbuffer buf1;
msgpack::packer<msgpack::sbuffer> bufPkr1(&buf1);
bufPkr1.pack_array(num);
for (int ndx = 0; ndx < num; ++ndx) {
bufPkr1.pack_array(3);
bufPkr1.pack(std::string("foo"));
bufPkr1.pack(std::string("bar"));
bufPrk1.pack(221);
}
msgpack::unpacked unPkd1;
msgpack::unpack(&unPkd1, buf1.data(), buf1.size());
const msgpack::object obj1 = respUnPk.get();
msgpack::sbuffer buf2;
msgpack::packer<msgpack::sbuffer> bufPkr2(&buf2);
bufPkr2.pack(obj1);
Если я правильно понимаю ваш вопрос, вы хотите упаковать данные в buf1 в виде необработанного двоичного изображения. Тогда вы хотите распаковать его.
Первая проблема — использование конструктора std :: vector. Смотрите комментарий P1 в следующем коде:
#include <msgpack.hpp>
#include <iostream>
#include <iomanip>
#include <algorithm>
int main() {
int const num = 5;
msgpack::sbuffer buf1;
msgpack::packer<msgpack::sbuffer> bufPkr1(&buf1);
bufPkr1.pack_array(num);
for (int ndx = 0; ndx < num; ++ndx) {
bufPkr1.pack_array(3);
bufPkr1.pack(std::string("foo"));
bufPkr1.pack(std::string("bar"));
bufPkr1.pack(221);
}
// P1
// std::vector<char> chrVct = std::vector<char>(buf1.size(), *buf1.data());
std::vector<char> chrVct = std::vector<char>(buf1.data(), static_cast<char*>(buf1.data()) + buf1.size());
msgpack::unpacked unPkd1;
msgpack::unpack(&unPkd1, buf1.data(), buf1.size());
msgpack::object toStr1 = unPkd1.get();
std::cout << "MsgPack1: " << toStr1 << std::endl;
msgpack::sbuffer buf2;
msgpack::packer<msgpack::sbuffer> bufPkr2(&buf2);
// P2
// bufPkr1.pack_raw(chrVct.size());
// bufPkr1.pack_raw_body(chrVct.data(), chrVct.size());
bufPkr2.pack_raw(chrVct.size());
bufPkr2.pack_raw_body(chrVct.data(), chrVct.size());
msgpack::unpacked unPkd2;
msgpack::unpack(&unPkd2, buf2.data(), buf2.size());
msgpack::object toStr2 = unPkd2.get();
std::cout << "MsgPack2: " << toStr2.via.raw.size << std::endl;
std::for_each(toStr2.via.raw.ptr, toStr2.via.raw.ptr+toStr2.via.raw.size,
[](char e) {
std::cout << std::hex << std::setw(2) << std::setfill('0') << (static_cast<int>(e) & 0xff) << ' ';
});
std::cout << std::endl;
}
Конструктор std :: vector в исходном коде заполняет все элементы вектора тем же значением, которое передается в качестве второго параметра.
Это (2) из следующей документации:
http://www.cplusplus.com/reference/vector/vector/vector/
Я считаю, что в этой ситуации следует использовать третий конструктор, Range Range. Поэтому я заменил оригинальный код на модифицированный.
Вторая проблема заключается в том, что bufPkr2 никогда не используется. Я думаю, что это просто опечатка. Я закомментировал оригинальный код и заменил его.
В результате этих изменений я получил следующий результат:
MsgPack1: [["foo", "bar", 221], ["foo", "bar", 221], ["foo", "bar", 221], ["foo", "bar", 221], ["foo", "bar", 221]]
MsgPack2: 56
95 93 a3 66 6f 6f a3 62 61 72 cc dd 93 a3 66 6f 6f a3 62 61 72 cc dd 93 a3 66 6f 6f a3 62 61 72 cc dd 93 a3 66 6f 6f a3 62 61 72 cc dd 93 a3 66 6f 6f a3 62 61 72 cc dd