1 场景
在项目开发中往往有这样的需求出现,需要将一个对象串行化成字符串之后,通过网络传到远方或者写入数据库,另一个程序再将这个字符串取出来反串行化成对象。一般在开发网络通讯当中都会有这样的需求,根据不同的对象结构我们不断的编写串行化和反串行化的操作,相当的麻烦,然而thrift就提供了一个很好的方案,只需要一个脚本,一个命令,就可以生成我们需要的代码,因此下面我会通过例子讲解如何使用thrift串行化对象。
2 思路
按照thrift的4层结构,由于我们不需要做rpc,因此不需要处理器层和服务器层,传输层不需要传到其它机器或写入数据库,只需写在内存中即可,因此选择TMemoryBuffer,协议就选择比较简单的TBinaryProtocol。
3 开发
3.1 编写脚本
message.thrift
//消息头
struct Head
{
1:i32 id;
2:string from;
3:string to;
}
//消息体
struct Body
{
1:i16 code;
2:string msg;
}
//消息
struct Message
{
1:Head mHead;
2:Body mBody;
}
主要是有一个Message的对象,里头有消息头和消息体,都分别有各自的属性。
3.2 使用thrift命令将脚本生成代码
$>thrift -gen cpp message.thrfit
这时,当前目录下生成了一个gen-cpp的目录,里头有4个文件:
message_types.h
message_types.cpp
message_constants.h
message_constants.cpp
而我们需要的只是message_types.h和message_types.cpp,因此将这两个文件拷贝出来
3.3 编写调用方法
thrift_archive.hpp
#pragma once
#include <boost/shared_ptr.hpp>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/protocol/TProtocol.h>
#include <thrift/protocol/TBinaryProtocol.h>
using namespace apache::thrift;
using namespace apache::thrift::transport;
using namespace apache::thrift::protocol;
template<typename T>
void thrift_iserialize(T& tag, std::string& s)
{
boost::shared_ptr<TMemoryBuffer> trans(
new TMemoryBuffer((uint8_t*)&s[0], s.size()));
boost::shared_ptr<TProtocol> proto(new TBinaryProtocol(trans));
tag.read(proto.get());
}
template<typename T>
void thrift_oserialize(T& tag, std::string& s)
{
boost::shared_ptr<TMemoryBuffer> trans(new TMemoryBuffer());
boost::shared_ptr<TProtocol> proto(new TBinaryProtocol(trans));
tag.write(proto.get());
s = trans->getBufferAsString();
}
main.cpp
#include <iostream>
#include "thrift_archive.hpp"
#include "message_types.h"
int main()
{
Message msg;
std::string s;
msg.mHead.id = 1;
msg.mHead.from = "";
msg.mHead.to = "";
msg.mBody.code = 100;
msg.mBody.msg = "hello";
thrift_oserialize(msg, s);
std::cout << s <<std::endl;
Message tmp;
thrift_iserialize(tmp, s);
return 0;
}
3.4 编写cmake编译
因为刚学会了cmake脚本的编写,因此也记下来以免忘记,当然也可以用g++直接编译
g++ -o test -DHAVE_NETINET_IN_H -I/usr/local/thrift/include -I/usr/local/boost/include -L/usr/local/thrift/lib -L/usr/local/boost/lib -lthriftnb -lthrift -levent message_types.cpp main.cpp
CMakeLists.txt
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(test)
MESSAGE(STATUS "Project: ${PROJECT_NAME}")
MESSAGE(STATUS "Project Directory: ${PROJECT_SOURCE_DIR}")
SET(CMAKE_BUILE_TYPE DEBUG)
SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall")
ADD_DEFINITIONS("-DHAVE_NETINET_IN_H")
INCLUDE_DIRECTORIES(
${PROJECT_SOURCE_DIR}/include
/usr/local/boost/include
/usr/local/thrift/include
/usr/local/log4cxx/include
)
LINK_DIRECTORIES(
${PROJECT_SOURCE_DIR}/lib
/usr/local/boost/lib
/usr/local/thrift/lib
/usr/local/log4cxx/lib
)
SET(SOURCE_FILES
main.cpp
message_types.cpp
)
ADD_EXECUTABLE(test ${SOURCE_FILES})
TARGET_LINK_LIBRARIES(test thrift thriftnb)
执行命令:
$>cmake .
$>make
然后再用gdb调试就可以看到结果了。