MsgPack Woes — Destructor, pack_raw_body, Etc

я использую 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, и я нахожу документацию / примеры немного скудными. Любая помощь, которую могут предложить люди, будет высоко ценится!

0

Решение

Одна из особенностей 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);
0

Другие решения

Если я правильно понимаю ваш вопрос, вы хотите упаковать данные в 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
0

По вопросам рекламы [email protected]