我使用MsgPack
作为为SOCI
C++数据库访问API创建的自定义后端的一部分。最初,我的一些SOCI
类将MsgPack::sbuffer
对象作为成员变量,但我在SOCI
对象的析构函数中遇到了一些问题——我认为这个问题与SOCI
引用计数其某些对象的方式以及MsgPack
对象的内存被多次释放有关。
为了解决这个问题,我决定用std::vector<char>
成员变量替换MsgPack::sbuffer
成员变量,并使用pack_raw_body
方法填充MsgPack::sbuffer
。不幸的是,我在这方面也遇到了麻烦。
请考虑以下(伪(代码片段。。。
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对象,并且发现文档/示例有点稀疏。如果人们能提供任何帮助,我们将不胜感激!
MsgPack API的一个古怪之处似乎与各种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构造函数将所有vector成员填充为与第二个参数相同的值。
这是以下文件的(2(:
http://www.cplusplus.com/reference/vector/vector/vector/
我认为第三个构造函数,范围版本,应该用于这种情况。所以我用修改后的代码替换了原来的代码。
第二个问题是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