4

Im trying to work with msgpack. I have a receiver and a sender. Sender is a c++ client and the receiver is an erlang server. Msgpack was totally great when I had an erlang server and an erlang client. I used to send and receive datatypes like lists, tuples, maps, binary, erlang and msgpack:pack() and msgpack:unpack() were totally fine. But when I started to change my sender to a c++ client, I started to think about this:

Can msgpack pack user-defined data-structures like classes and structures. ? What if I have a complex structure and pack that using msgpack:pack() and on the receiver end, when I use msgpack:unpack() can I tell it to decode to a specific data-type Im interested in? may be a tuple ?

Thanks. !

sad
  • 820
  • 1
  • 9
  • 16
  • 1
    http://www.thomaswhitton.com/blog/2013/07/03/binary-message-format-c-plus-plus-examples/. Check the message pack section. – Arunmu Nov 30 '16 at 19:46

1 Answers1

4

Can msgpack pack user-defined data-structures like classes and structures. ?

Yes you can do it. msgpack-c supports both C and C++. And I wrote about the C++ part of msgpack-c. msgpack-c can pack any types that have the adaptor. Here is a list of a pre-supported C++ types https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_adaptor

And you can also write adaptors for user defined types. The simplest approach is using MSGPACK_DEFINE (mapped to ARRAY) or MSGPACK_DEFINE_MAP (mapped to MAP).

You can combine and composite any types as long as the types have adaptors. If you write MSGPACK_DEFINE in your_type, you can pack std::vector<std::map<std::string, your_type> >.

What if I have a complex structure and pack that using msgpack:pack() and on the receiver end, when I use msgpack:unpack() can I tell it to decode to a specific data-type Im interested in? may be a tuple ?

When you unpack MessageePack formatted data, you get msgpack::object_handle. See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_unpacker.

Then you can get msgpack::object from msgpack::object_handle. Finally, you can convert from msgpack::object to any types that have adaptors using as() member function. See https://github.com/msgpack/msgpack-c/wiki/v2_0_cpp_object#conversion

Here is an example code:

#include <iostream>
#include <sstream>
#include <cassert>
#include <msgpack.hpp>

struct your_type {
    int a;
    int b;
    MSGPACK_DEFINE(a, b);
};

bool operator==(your_type const& lhs, your_type const& rhs) {
    return lhs.a == rhs.a && lhs.b == rhs.b;
}

int main() {
    // packing
    std::stringstream ss;
    std::vector<std::map<std::string, your_type>> v 
    { 
        { 
            { "key1", {1,2} },
            { "key2", {3,4} }
        },
        {
            {"key3", {5, 6} } 
        }
    };
    msgpack::pack(ss, v);

    // unpacking
    msgpack::object_handle oh = msgpack::unpack(ss.str().data(), ss.str().size());
    msgpack::object const& obj = oh.get();
    std::cout << "object: " << obj << std::endl;

    // converting
    auto v2 = obj.as<std::vector<std::map<std::string, your_type>>>();
    assert(v == v2);
}

And you can run, and modify it in the Wandbox, online compiler environment: http://melpon.org/wandbox/permlink/M229kOVY6ys83pwb

Takatoshi Kondo
  • 3,111
  • 17
  • 36