msgpack定义了几个序列化宏,使用这些宏,可大大简化我们的序列化的代码。
可用的宏如下:
MSGPACK_DEFINE 声明要用msgpack序列化的变量
MSGPACK_BASE 声明要用msgpack序列化的基类类型
MSGPACK_DEFINE_ARRAY 以数组/顺序方式序列化
MSGPACK_DEFINE_MAP 以键值对方式序列化
MSGPACK_BASE_ARRAY 以数组/顺序方式序列化基类
MSGPACK_BASE_MAP 以键值对方式序列化基类
其中MSGPACK_DEFINE , MSGPACK_BASE 在定义了MSGPACK_USE_DEFINE_MAP时,会被定义为MSGPACK_DEFINE_MAP和MSGPACK_BASE_MAP,否则会被定义为MSGPACK_DEFINE_ARRAY和MSGPACK_BASE_ARRAY
默认情况下MSGPACK_USE_DEFINE_MAP不会被定义,但MSGPACK_DEFINE_MAP和MSGPACK_BASE_MAP仍可使用。
// 使用实例(以数组/顺序方式序列化):
struct ShareVideo
{
string m_videoId;
int m_time;
string m_userNike[4];
int m_score[4];
MSGPACK_DEFINE_ARRAY(m_videoId, m_time, m_userNike[0], m_userNike[1],
m_userNike[2], m_userNike[3], m_score[0],m_score[1],m_score[2],m_score[3])
// 不需要";"
};
struct Msg
{
Msg(int id);
virtual~Msg();
int m_msgId;
MSGPACK_DEFINE_ARRAY(m_msgId)
};
struct MsgShareVideo:public Msg
{
int m_count;
int m_errorId;//0失败 1成功
std::vector<ShareVideo> m_vec_share_video;
MsgShareVideo() :Msg(MSG_SHAREVIDEO),m_errorId(0),m_count(0){}
MSGPACK_DEFINE_ARRAY(MSGPACK_BASE_ARRAY(Msg), m_count, m_errorId,
m_vec_share_video)
virtual bool Read(msgpack::object& obj)
{
obj.convert(*this);
return true;
}
virtual bool Write(msgpack::packer<msgpack::sbuffer>& pack)
{
pack.pack(*this);
return true;
}
}
///
// 使用实例(以键值对方式序列化):
struct ShareVideo
{
string m_videoId;
int m_time;
string m_userNike[4];
int m_score[4];
MSGPACK_DEFINE_MAP(
m_videoId, // 展开后key:value = "m_videoId":m_videoId
m_time,
(m_userNike0), (m_userNike[0]), // key:value = "m_userNike0":m_userNike[0]
(m_userNike1), (m_userNike[1]), // 使用“()"可阻止msgpack宏展开
(m_userNike2), (m_userNike[2]),
(m_userNike3), (m_userNike[3]),
m_score[0], // 展开后key:value = "m_score[0]":m_score[0]
m_score[1],
m_score[2],
m_score[3]
)
// 不需要";"
};
struct Msg
{
Msg(int id);
virtual~Msg();
Lint m_msgId;
MSGPACK_DEFINE_MAP(m_msgId)
};
struct MsgShareVideo:public LMsg
{
int m_count;
int m_errorId;//0失败 1成功
std::vector<ShareVideo> m_vec_share_video;
MsgShareVideo() :Msg(MSG_SHAREVIDEO),m_errorId(0),m_count(0){}
// 写法1,基类成员在基类对象中
// 序列化后
// {
// "Msg": {"m_msgId": m_msgId},
// "m_count": m_count,
// "m_errorId": m_errorId,
// "m_vec_share_video":
// [
// {
// "m_videoId":m_videoId,
// "m_time":m_time,
// "m_userNike0":m_userNike[0],
// "m_userNike1":m_userNike[1],
// "m_userNike2":m_userNike[2],
// "m_userNike3":m_userNike[3],
// "m_score[0]":m_score[0],
// "m_score[1]":m_score[1],
// "m_score[2]":m_score[2],
// "m_score[3]":m_score[3],
// },
// ...
// ]
// }
MSGPACK_DEFINE_MAP(MSGPACK_BASE_MAP(Msg), m_count, m_errorId,
m_vec_share_video)
// 写法2, 将基类成员扁平化
// MSGPACK_DEFINE_MAP(m_msgId, m_count, m_errorId,
// m_vec_share_video)
virtual bool Read(msgpack::object& obj)
{
obj.convert(*this);
return true;
}
virtual bool Write(msgpack::packer<msgpack::sbuffer>& pack)
{
pack.pack(*this);
return true;
}
}
定长数组写的太麻烦?可以用std::array来申明定长数组
struct ShareVideo
{
string m_videoId;
int m_time;
std::array<string,4> m_userNike;
std::array<int,4> m_score;
MSGPACK_DEFINE_MAP(
m_videoId, // 展开后key:value = "m_videoId":m_videoId
m_time,
m_userNike, // key:value = "m_userNike":[m_userNike[0],...]
m_score // 展开后key:value = "m_score":[m_score[0],...]
)
};
msgpack宏的高级用法:
MSGPACK_PP_SEQ_FOR_EACH(macro, data, seq) 宏循环
#define DO_WRITE(r, data, elem) buff.write(elem);
#define MSG_WRITE(...) \
virtual void write(LBuff& buff)\
{\
MSGPACK_PP_SEQ_FOR_EACH(\
DO_WRITE, \
0, \
MSGPACK_PP_VARIADIC_TO_SEQ(__VA_ARGS__) \
)\
}
class Test
{
public:
Lint a1;
Lint a2;
Lint a3;
Lint a4;
Lint a5;
MSG_WRITE(a1, a2, a3, a4, a5)
// 展开后
// virtual void write(LBuff& buff){ buff.write(a1 ); buff.write(a2 ); buff.write(a3 );
// buff.write (a4 ); buff.write(a5 ); }
};