Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to msgpack a user-defined C++ class with POD-arrays?

Tags:

c++

api

msgpack

How it is possible to provide all three functions: msgpack_pack, msgpack_unpack and msgpack_object (also, what are meanings of them, exactly?) for a user-defined C++ class (in the same way MSGPACK_DEFINE does it for non-array POD/UD types) containing Plain Old Data arrays (such as dobule[] or char[]), so my class will play nicely with higher-level classes, containg this class in map or a vector?

Is there any examples of implementing them for your own class or at least msgpack C++ api documentation?

The only link to possible api reference i've found was http://redmine.msgpack.org/projects/msgpack/wiki ; but it is dead now.

Say, i have a struct like

struct entity {
  const char name[256];
  double mat[16];
};

What would be a msgpack_* member functions for it?

like image 491
Alexander Tumin Avatar asked May 11 '13 14:05

Alexander Tumin


1 Answers

Thanks to guy who -1'd my question, i felt grievance and explored the actual undocumented codebase of msgpack. Here is the example of mentioned earlier functions with sort of explanation, in amount of my (vastly incomplete due to missing docs) understanding:

struct entity {
  char name[256];
  double mat[16];

  // this function is appears to be a mere serializer
  template <typename Packer>
  void msgpack_pack(Packer& pk) const {
    // make array of two elements, by the number of class fields
    pk.pack_array(2); 

    // pack the first field, strightforward
    pk.pack_raw(sizeof(name));
    pk.pack_raw_body(name, sizeof(name));

    // since it is array of doubles, we can't use direct conversion or copying
    // memory because it would be a machine-dependent representation of floats
    // instead, we converting this POD array to some msgpack array, like this:
    pk.pack_array(16);
    for (int i = 0; i < 16; i++) {
      pk.pack_double(mat[i]);
    }
  }

  // this function is looks like de-serializer, taking an msgpack object
  // and extracting data from it to the current class fields
  void msgpack_unpack(msgpack::object o) {
    // check if received structure is an array
    if(o.type != msgpack::type::ARRAY) { throw msgpack::type_error(); }

    const size_t size = o.via.array.size;

    // sanity check
    if(size <= 0) return;
    // extract value of first array entry to a class field
    memcpy(name, o.via.array.ptr[0].via.raw.ptr, o.via.array.ptr[0].via.raw.size);

    // sanity check
    if(size <= 1) return;
    // extract value of second array entry which is array itself:
    for (int i = 0; i < 16 ; i++) {
      mat[i] = o.via.array.ptr[1].via.array.ptr[i].via.dec;
    }
  }

  // destination of this function is unknown - i've never ran into scenary
  // what it was called. some explaination/documentation needed.
  template <typename MSGPACK_OBJECT>
  void msgpack_object(MSGPACK_OBJECT* o, msgpack::zone* z) const { 

  }
};
like image 152
Alexander Tumin Avatar answered Oct 07 '22 01:10

Alexander Tumin