使用Msgpack在C ++中打包ext类型

时间:2017-11-30 17:37:17

标签: c++ msgpack

我正在寻找一个示例如何在C ++中使用msgpack打包ext类型,因为我不知道如何执行此操作。

我找到的唯一信息位于此部分https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_packer#pack-manually

假设我想将类型为Foo的对象打包为带有适配器类模板的msgpack ext类型。如何使用pack_extpack_ext_body?我是否必须在模板中创建“子包装器”,手动打包我的Foo数据,然后将二进制数据和数据本身的大小传递给pack_extpack_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);
            }
       }
 }

}

提前致谢!

2 个答案:

答案 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::extmsgpack::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。 它可以避免复制操作,但您需要保留原始缓冲区,在这种情况下为valoh

#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);
}

现场演示: https://wandbox.org/permlink/uYr5MFjLJqPHQgj6