flatbuffers简介
FlatBuffers 是一个(二进制 buffer)序列化开源库,由 Google 开源现在它支持C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift等。
特点
- 无需解析/解包即可访问序列化数据;
- 强类型;
- 使用方便;
- 无依赖的跨平台代码;
与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::vector<std::string> 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::vector<std::string> &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<Jflat::FbFunction> createFbFunction(flatbuffers::FlatBufferBuilder &builder) const; 32 33 flatbuffers::Offset<Jflat::FbMessage> createFbMessage(flatbuffers::FlatBufferBuilder &builder) const override; 34 35 std::shared_ptr<flatbuffers::DetachedBuffer> 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::vector<std::string>()), 5 return_value("") 6 { 7 mObjType = Jflat::FbDataHeadType_FBT_RFC; 8 } 9 10 JFunction::JFunction(uint32_t tmp_func_id, std::vector<std::string> &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<flatbuffers::DetachedBuffer> JFunction::serializeAsFlat() const 60 { 61 flatbuffers::FlatBufferBuilder builder; 62 auto flat = createFbMessage(builder); 63 builder.Finish(flat); 64 65 return std::make_shared<flatbuffers::DetachedBuffer>(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<Jflat::FbFunction> 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<Jflat::FbMessage> 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 <iostream> 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 }