Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

v1_0_cpp_versioning

Takatoshi Kondo edited this page Apr 3, 2015 · 2 revisions

API versioning on C++

msgpack-c have introduced API versioning mechanism.

Macros

MSGPACK_DEFAULT_API_VERSION

MSGPACK_DEFAULT_API_VERSION means the default version of msgpack-c API. The current value is 1.

#if !defined(MSGPACK_DEFAULT_API_VERSION)
#define MSGPACK_DEFAULT_API_VERSION 1
#endif

When you want to set MSGPACK_API_VERSION explicitly, give the macro value as follows:

g++ -DMSGPACK_API_VERSION=2

MSGPACK_DEFAULT_API_NS

MSGPACK_DEFAULT_API_NS is a namespace name of the default msgpack version. It names 'v' + MSGPACK_DEFAULT_API_VERSION. e.g.) v1, v2, ...

It is used when you declare and define your custom overloads of operators.

See the following example:

https://github.com/msgpack/msgpack-c/blob/cpp-1.0.1/example/cpp03/class_non_intrusive.cpp#L28

https://github.com/msgpack/msgpack-c/blob/cpp-1.0.1/example/cpp03/class_non_intrusive.cpp#L67

MSGPACK_API_VERSION_NAMESPACE

MSGPACK_API_VERSION_NAMESPACE is a function style macro. It defines a namespace. You can pass an argument as the namespace you want to define.

MSGPACK_API_VERSION_NAMESPACE(v1) {
   // ...
}

MSGPACK_API_VERSION_NAMESPACE(v2) {
   // ...
}

The macro is expanded to namespace. If the given namespace name is same as MSGPACK_DEFAULT_API_NS, the macro is expanded as follows:

In the case MSGPACK_DEFAULT_API_NS == v1

C++11

inline namespace v1 {
   // ...
}

namespace v2 {
   // ...
}

C++03

namespace v1{}; using namespace v1; namespace v1 {
   // ...
}

namespace v2 {
   // ...
}

It is used when you declare and define your custom overloads of operators.

See the following example:

https://github.com/msgpack/msgpack-c/blob/cpp-1.0.1/example/cpp03/class_non_intrusive.cpp#L28

https://github.com/msgpack/msgpack-c/blob/cpp-1.0.1/example/cpp03/class_non_intrusive.cpp#L67

Overloading operators

When you want to adapt your class to msgpack-c, you have two choice. One is intrusive approach, the other is non-intrusive approach.

Intrusive approach

You just add MSGPACK_DEFINE macro on the public are of your class.

// Both ok.
#include <msgpack_fwd.hpp>
// or
#include <msgpack.hpp>

class your_class {
public:
    your_class() {} // The class needs to be default constructible
                    // when you want to convert from msgpack::object
                    // to your_class.
    your_class(int mem1, std::string const& mem2)
        :mem1_(mem1), mem2_(mem2) {}

private:
    // Data members can be private.
    int mem1_;
    std::string mem2_;

public:
    // Define the following macro as public:
    MSGPACK_DEFINE(mem1_, mem2_);
};

// When you include msgpack_fwd.hpp above, you need to include msgpack.h
// somewhere.
#include <msgpack.hpp>

Non-intrusive approach

Sometimes you can't modify the class you want to adapt msgpack-c. For example the class is a part of the third party library. You need to declrare and define operators as the following mannar:

// Include msgpack_fwd.hpp before your overloads are declared.
// Don't include msgpack.hpp here.
#include <msgpack_fwd.hpp>

// Declare the target class.
// Or include third_class_fwd.hpp if it's provided.
class third_class;

namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {

// Declare operators

// For convert third_class form msgpack::object.
object const& operator>> (msgpack::object const& o, third_class& v);


// For pack.
template <typename Stream>
packer<Stream>& operator<< (msgpack::packer<Stream>& o, third_class const& v);

// For create object::with_zone from third_class.
void operator<< (msgpack::object::with_zone& o, const third_class& v);


} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
} // namespace msgpack


// Define third_class or include third_class.hpp.
class third_class {
public:
    third_class() {} // The class needs to be default constructible
                     // when you want to convert from msgpack::object
                     // to third_class.
    third_class(int mem1, std::string const& mem2)
        :mem1_(mem1), mem2_(mem2) {}

    // The class need to provide getter functions that return
    // the values you want to pack.
    int get_mem1() const { return mem1_; }
    std::string get_mem2() const { return mem2_; }

private:
    // Data members can be private.
    int mem1_;
    std::string mem2_;
};

// include msgpack.hpp after your overloads declared.
#include <msgpack.hpp>

namespace msgpack {
MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS) {

// Declare operators after msgpack.hpp included

// For convert third_class form msgpack::object.
inline object const& operator>> (msgpack::object const& o, third_class& v) {
    if (o.type != msgpack::type::ARRAY) throw msgpack::type_error();
    if (o.via.array.size != 2) throw msgpack::type_error();
    v = third_class(
        o.via.array.ptr[0].as<int>(),
        o.via.array.ptr[1].as<std::string>());
    return o;
}


// For pack.
template <typename Stream>
inline packer<Stream>& operator<< (msgpack::packer<Stream>& o, third_class const& v) {
    // packing member variables as an array.
    o.pack_array(2);
    o.pack(v.get_mem1());
    o.pack(v.get_mem2());
    return o;
}

// For create object::with_zone from third_class.
inline void operator<< (msgpack::object::with_zone& o, const third_class& v) {
    o.type = type::ARRAY;
    msgpack::object* p = static_cast<object*>(o.zone.allocate_align(sizeof(msgpack::object)*2));
    o.via.array.ptr = p;
    o.via.array.size = 2;
    p[0] = msgpack::object(v.get_mem1(), o.zone);
    p[1] = msgpack::object(v.get_mem1(), o.zone);
}

} // MSGPACK_API_VERSION_NAMESPACE(MSGPACK_DEFAULT_API_NS)
} // namespace msgpack

You only define operator<< (msgpack::object::with_zone& o, const third_class& v) overload only when you want to use msgpack::object::with_zone.

Implementation note

See this discussion.

Clone this wiki locally

Morty Proxy This is a proxified and sanitized view of the page, visit original site.