使用thrift串行化对象

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();
}


因为感觉对象的串行化和反串行化是会经常使用的,因此写成了两个函数模板,thrift_iserialize是将字符串反串行化成对象,而thrift_oserialize是将对象串行化成字符串。


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;
}


先实例化一个Message的对象msg,对这个对象设置属性值,然后串行化到字符串s上,再将s反串行化到tmp对象上,最后msg和tmp的属性值是一致。


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调试就可以看到结果了。


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值