码迷,mamicode.com
首页 > 其他好文 > 详细

thrift c_glib 库序列化学习

时间:2016-01-08 13:21:35      阅读:2439      评论:0      收藏:0      [点我收藏+]

标签:

thrift c_glib 库序列化学习

最近在项目中需要在不同的语言(c, c++, java, python) 之间传递消息, 模式是 server(C++)需要向订阅者(observer) 发送更新.
大致的思路是server侦听某个端口, 然后observer 连接, 然后双方保持连接, 当有更新时, server 将消息下发给observer.
由于需要跨语言,所以我们需要一个序列化的库, 项目中之前引入的thrift 正好可以解决, 在需要支持的各种语言中, c语言由于本身没有面向对象, 所以特别单独学习了下thrift c_glib 的使用, 特此记录.

thrift c_glib

  1. thrift 是一个跨语言的RPC库, 自身带了很不错的网络框架,使用起来很简单, 基本上只需要很短的代码量就可以实现一个基于socket/HTTP的模式, 但是这个模式需要client端主动发起请求,然后server应答, 和我们的设计不太一致, 所以这里我只是把thrift 作为一个序列化的库来使用
  2. thrift 支持很多语言, 比如C++, Java, Python 等等, 但是它对C语言的支持需要glib 库, 并不是原生支持, 所以需要熟悉下glib库的用法

thrift c_glib 序列化例子

在安装好thrift 后, 我们需要编写消息体, 保存为 test.thrift
  1. struct test {
      1:boolean b1,
      2:i32 i2,
      3:string s3
    }

可以注意到这里的格式,非常类似c, 然后执行命令

  thrift -r --gen c_glib test.thrift

就会在gen-c_glib文件夹中生成对应的代码文件test_types.h, test_types.c
test_types.h 中定义了一些我们会用到的宏, 以及两个主要的结构体

  1. struct _test
    {
    ThriftStruct parent;
    /* public */
    gint32 i1;
    gboolean __isset_i1;
    gchar * s2;
    gboolean __isset_s2;
    };
    typedef struct _test test;
    struct _testClass
    {
    ThriftStructClass parent;
    };
    typedef struct _testClass testClass;
    GType test_get_type (void);
    #define TYPE_TEST (test_get_type())
    #define TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TEST, test))
    #define TEST_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), _TYPE_TEST, testClass))
    #define IS_TEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TEST))
    #define IS_TEST_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TYPE_TEST))
    #define TEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TEST, testClass))
编写序列化过程
  1. #include <string.h>
    #include <stdio.h>
    #include <glib-object.h>
    #include <thrift/c_glib/protocol/thrift_binary_protocol.h>
    #include <thrift/c_glib/transport/thrift_memory_buffer.h>
    #include "gen-c_glib/test_types.h"
    test* createTest(int num, const char* mesg)
    {
      test* t = g_object_new(TYPE_TEST, NULL);
      t->i1 = num;
      t->s2 = strdup(mesg);
      return t;
    }
    guchar* test2String(test* t, int* size) {
      ThriftTransport * transport = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", 1024, NULL));
      ThriftProtocol * protocol = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL));
      thrift_struct_write(THRIFT_STRUCT(t), protocol, NULL);
      guchar* buf = (guchar*) g_malloc0(1024);
      *size = thrift_memory_buffer_read(THRIFT_TRANSPORT(transport), buf, 1024, NULL);
      g_object_unref(transport);
      g_object_unref(protocol);
      return buf;
    }
    test* string2Test(const guchar* buf, int size) {
      ThriftTransport * transport = THRIFT_TRANSPORT(g_object_new(THRIFT_TYPE_MEMORY_BUFFER, "buf_size", size, NULL));
      ThriftProtocol * protocol = THRIFT_PROTOCOL(g_object_new(THRIFT_TYPE_BINARY_PROTOCOL, "transport", transport, NULL));
      thrift_memory_buffer_write(transport, (gpointer)buf, size, NULL);
      test* t = g_object_new(TYPE_TEST, NULL);
      thrift_struct_read(THRIFT_STRUCT(t), protocol, NULL);
      g_object_unref(transport);
      g_object_unref(protocol);
      return t;
    }
    int main() {
      test * t = createTest(1024, "hello");
      int size;
      guchar* buf = test2String(t, &size);
      g_object_unref(t);
      test * nt = string2Test(buf, size);
      g_free(buf);
      printf("%d %s\n", nt->i1, nt->s2);
      g_object_unref(nt);
      return 0;
    }

     

通过这样, 剩下的就只是server通过socket将转换成guchar的字符串 发送给客户端, 客户端在进行反序列化就可以得到信息了

thrift c_glib 库序列化学习

标签:

原文地址:http://www.cnblogs.com/gtsfreer/p/5112827.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!