我正在寻找一个示例如何在C ++中使用msgpack打包ext类型,因为我不知道如何执行此操作。
我找到的唯一信息位于此部分https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_packer#pack-manually。
假设我想将类型为Foo的对象打包为带有适配器类模板的msgpack ext类型。如何使用pack_ext
和pack_ext_body
?我是否必须在模板中创建“子包装器”,手动打包我的Foo数据,然后将二进制数据和数据本身的大小传递给pack_ext
和pack_ext_body
?如果一些C ++专家可以给我一个最小的例子,那将是创造。
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor {
template<>
struct pack<Foo> {
template <typename Stream>
packer<Stream>& operator()(msgpack::packer<Stream>& o, Foo const& v) const {
// how to use ?
o.pack_ext(size_t l, int8_t type);
o.pack_ext_body(const char* b, size_t l);
}
}
}
}
提前致谢!
答案 0 :(得分:0)
我让它与我的&#34; sub packer&#34;理念。我不知道这是一个好的和优雅的解决方案,但至少它是有效的:
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {
namespace adaptor {
template<>
struct pack<Foo> {
template <typename Stream>
packer<Stream>& operator()(msgpack::packer<Stream>& o, Foo const& v) const {
msgpack::sbuffer sbuf;
msgpack::packer<msgpack::sbuffer> sub_packer(sbuf);
sub_packer.pack_map(2);
sub_packer.pack("name");
sub_packer.pack(v.name);
sub_packer.pack("bar");
sub_packer.pack(v.bar);
// get binary data from sub_packer's sbuffer
size_t l = sbuf.size();
const char* b = sbuf.data();
// pass ext type and binary data to originally packer
o.pack_ext(l, 1);
o.pack_ext_body(b, l);
return o;
}
}
}
}
答案 1 :(得分:0)
您可以使用msgpack::type::ext
或msgpack::type::ext_ref
。
它们定义在https://github.com/msgpack/msgpack-c/blob/master/include/msgpack/v1/adaptor/ext.hpp
以下是msgpack::type::ext
的示例:
#include <sstream>
#include <cassert>
#include <msgpack.hpp>
int main() {
std::string val = "ABC";
msgpack::type::ext e1(42, val.data(), val.size());
assert(e1.type() == 42);
assert(e1.size() == 3);
assert(e1.data()[0] == 'A');
assert(e1.data()[1] == 'B');
assert(e1.data()[2] == 'C');
std::stringstream ss;
msgpack::pack(ss, e1);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto e2 = oh.get().as<msgpack::type::ext>();
assert(e1 == e2);
}
现场演示: https://wandbox.org/permlink/ESmreWNBqDdXbKSf
您也可以使用msgpack::type::ext_ref
。
它可以避免复制操作,但您需要保留原始缓冲区,在这种情况下为val
和oh
。
#include <sstream>
#include <cassert>
#include <msgpack.hpp>
int main() {
std::string val = "\x2a"; // type 42
val += "ABC";
msgpack::type::ext_ref e1(val.data(), val.size());
assert(e1.type() == 42);
assert(e1.size() == 3);
assert(e1.data()[0] == 'A');
assert(e1.data()[1] == 'B');
assert(e1.data()[2] == 'C');
std::stringstream ss;
msgpack::pack(ss, e1);
auto oh = msgpack::unpack(ss.str().data(), ss.str().size());
auto e2 = oh.get().as<msgpack::type::ext_ref>();
assert(e1 == e2);
}