Flatbuffers学习


flatbuffers简介

FlatBuffers 是一个(二进制 buffer)序列化开源库,由 Google 开源现在它支持C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift等。 官网:http://google.github.io/flatbuffers/  

特点

  1. 无需解析/解包即可访问序列化数据;
  2. 强类型;
  3. 使用方便;
  4. 无依赖的跨平台代码;

与Protocol Buffers的比较(优点):

  使用过程中,我觉得flat对比proto最大的优点就是“零拷贝”反序列化,如果你需要大量的反序列化,flat要比proto更合适一些。    

FlatBuffers schema

 
 1 #include "FbBasicType.fbs";       // 消息头的类型,时间戳等等
 2 
 3 namespace Jflat;
 4 
 5 table FbFunction{
 6     func_id         : uint32;
 7     param_list      : [string];   // vector类型
 8     return_value    : string;
 9 }
10 
11 root_type FbFunction;            // root_type声明序列化数据的object

FlatBuffers schema compilation

  使用“flatc”编译.fbs文件,它将为对应编程语言创建生成代码。

1 flatc --gen-mutable --gen-object-api --reflect-names --cpp-ptr-type flatbuffers::unique_ptr --gen-compare  --json --cpp --java --js --python *.fbs #--gen-all
2 
3       --gen-mutable          Generate accessors that can mutate buffers in-place.
4       --gen-object-api       Generate an additional object-based API.
5       --reflect-names        Add minimal type/name reflection.
6       --gen-compare          Generate operator== for object-based API types.

FlatBuffers serialization methods

.h文件

 1 #ifndef JFUNCTION_H
 2 #define JFUNCTION_H
 3 
 4 #include "JflatHeader.h"
 5 
 6 class JFunction : public JflatHeader
 7 {
 8 public:
 9 
10     uint32_t                    func_id;
11     std::vectorstring>    param_list;
12     std::string                 return_value;
13 
14 public:
15     JFunction();
16 
17     explicit JFunction(const uint8_t *tmp_data);
18 
19     explicit JFunction(uint32_t tmp_func_id, std::vectorstring> &tmp_param_list, const std::string &tmp_return_value);
20 
21     JFunction(const JFunction &tmp);
22 
23     JFunction &operator=(const JFunction &tmp);
24 
25     ~JFunction() = default;
26 
27     std::string str();
28             
29     const Jflat::FbMessage *getFbMessage(const uint8_t *data);
30 
31     flatbuffers::Offset createFbFunction(flatbuffers::FlatBufferBuilder &builder) const;
32 
33     flatbuffers::Offset createFbMessage(flatbuffers::FlatBufferBuilder &builder) const override;
34 
35     std::shared_ptr serializeAsFlat() const;
36 
37     bool deserialize(const uint8_t *data) override;
38 
39     bool getFbFunction(const Jflat::FbFunction *flat_function);
40     
41     std::string serializeAsString() const;
42 
43 private:
44     void assignmentVariable(const JFunction &tmp);
45 };
46 
47 #endif //JFUNCTION_H

 .cpp文件

  1 #include "JFunction.h"
  2 
  3 JFunction::JFunction() : func_id(0),
  4                          param_list(std::vectorstring>()),
  5                          return_value("")
  6 {
  7     mObjType = Jflat::FbDataHeadType_FBT_RFC;
  8 }
  9 
 10 JFunction::JFunction(uint32_t tmp_func_id, std::vectorstring> &tmp_param_list, const std::string &tmp_return_value)
 11         : func_id(tmp_func_id),
 12           param_list(tmp_param_list),
 13           return_value(tmp_return_value)
 14 {
 15     mObjType = Jflat::FbDataHeadType_FBT_RFC;
 16 }
 17 
 18 JFunction::JFunction(const uint8_t *tmp_data)
 19 {
 20     mObjType = Jflat::FbDataHeadType_FBT_RFC;
 21     deserialize(tmp_data);
 22 }
 23 
 24 JFunction::JFunction(const JFunction &tmp)
 25 {
 26     mObjType = Jflat::FbDataHeadType_FBT_RFC;
 27     assignmentVariable(tmp);
 28 }
 29 
 30 JFunction &JFunction::operator=(const JFunction &tmp)
 31 {
 32     if (this != &tmp) assignmentVariable(tmp);
 33     return *this;
 34 }
 35 
 36 void JFunction::assignmentVariable(const JFunction &tmp)
 37 {
 38     QObject::assignmentVariable(tmp.mStamp, tmp.mId, tmp.mObjType);
 39 
 40     param_list.assign(tmp.param_list.begin(), tmp.param_list.end());
 41     func_id          = tmp.func_id;
 42     return_value     = tmp.return_value;
 43 }
 44 
 45 std::string JFunction::str()
 46 {
 47     return flatbuffers::FlatBufferToString(serializeAsFlat()->data(), Qflat::FbMessageTypeTable(), true);
 48 }
 49 
 50 std::string JFunction::serializeAsString() const
 51 {
 52     auto detached_buffer = serializeAsFlat();
 53     if (detached_buffer)
 54         return std::string((char *) detached_buffer->data(), detached_buffer->size());
 55     else
 56         return "";
 57 }
 58 
 59 std::shared_ptr JFunction::serializeAsFlat() const
 60 {
 61     flatbuffers::FlatBufferBuilder builder;
 62     auto flat = createFbMessage(builder);
 63     builder.Finish(flat);
 64   
 65     return std::make_shared(builder.Release());
 66 }
 67 
 68 const Jflat::FbMessage *JFunction::getFbMessage(const uint8_t *data)
 69 {
 70     auto data_flat  = Jflat::GetFbMessage(data);
 71     obj_type        = data_flat->header()->type();
 72     stamp           = data_flat->header()->stamp();
 73     id              = data_flat->header()->id();
 74 
 75     return data_flat;
 76 }
 77 
 78 flatbuffers::Offset JFunction::createFbFunction(flatbuffers::FlatBufferBuilder &builder) const
 79 {
 80     auto flat_param_list     = builder.CreateVectorOfStrings(param_list);
 81     auto flat_return_value   = builder.CreateString(return_value);
 82     auto flat_function       = Jflat::CreateFbFunction(builder, func_id, flat_param_list, flat_return_value);
 83 
 84     return flat_function;
 85 }
 86 
 87 flatbuffers::Offset JFunction::createFbMessage(flatbuffers::FlatBufferBuilder &builder) const
 88 {
 89     auto header_function     = Jflat::CreateFbMsgHeader(builder, Jflat::FbDataHeadType_FBT_RFC, mStamp, mId);
 90     auto flat_function       = createFbFunction(builder);
 91     auto flat                = Jflat::CreateFbMessage(builder, header_function, Jflat::FbMsgBody_FbFunction, flat_function.Union());
 92 
 93     return flat;
 94 }
 95 
 96 bool JFunction::deserialize(const uint8_t *data)
 97 {
 98     auto data_flat       = getFbMessage(data);
 99     auto flat_function   = data_flat->data_as_FbFunction();
100     getFbFunction(flat_function);
101 
102     return true;
103 }
104 
105 bool JFunction::getFbFunction(const Jflat::FbFunction *flat_function)
106 {
107     func_id = flat_function->func_id();
108 
109     param_list.clear();
110     for (const auto &flat_data : *flat_function->param_list())
111         param_list.emplace_back(std::string(flat_data->data(), flat_data->size()));
112 
113     return_value = std::string(flat_function->return_value()->data(), flat_function->return_value()->size());
114 
115     return true;
116

FlatBuffers example

 1 #include "JFunction.h"
 2 
 3 #include 
 4 
 5 #define FLAT_DATA_DIFF(before_data, after_data) \
 6 {   \
 7     if(!(before_data == after_data))   \
 8     {   \
 9         std::cout << #before_data << " : line" << __LINE__ << "========================== before =================================" << std::endl;    \
10         std::cout << before_data << std::endl;    \
11         std::cout << #after_data << " : line" << __LINE__ << "========================== after =================================" << std::endl;  \
12         std::cout << after_data << std::endl; \
13     }   \
14 }
15 
16 void assignment_JFunction_instance(JFunction &jFunction_1)
17 {
18     jFunction_1.func_id = 222;
19 
20     for (uint16_t i = 0; i < GENERIC_16_ARRAY_SIZE; ++i)
21         jFunction_1.param_list.push_back(std::to_string(i));
22 
23     jFunction_1.return_value = "return_value pi pi sha";   /// 嘿嘿嘿,我女朋友
24 }
25 
26 int main(void)
27 {
28     JFunction jFunction_1;
29     assignment_JFunction_instance(jFunction_1);
30     auto buf = jFunction_1.serializeAsFlat();
31     
32     JFunction jFunction_2(buf->data());
33     
34     FLAT_DATA_DIFF(jFunction_1.str(), jFunction_2.str());
35     
36     return 0;
37 }

所有代码仅供参考,记录我当时的应用方法。