c++对象的序列化与反序列化的解决方案----flatbuffers的使用_通用算法进行c++对象序列化-程序员宅基地

技术标签: flatbuffer  

c++对象的序列化与反序列化的解决方案----flatbuffers的使用

PushFlatBuffer

if(table)

return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf)

else

{return buf}

概述

  本篇blog主要是给大家介绍FlatBuffers的相关的信息和用法,当我在了解的FlatBuffers时,国内还没有一些相关的文章去介绍FlatBuffers,不得不FQ去google相关的用法,然后理解并应用到自己的代码中,学习的时间成本很高。所以就花了点时间整理一份具体的用法,提供给大家一个参考。

简介

一、什么是FlatBuffers?

  FlatBuffers是一个开源的、跨平台的、高效的、提供了C++/Java接口的序列化工具库。它是Google专门为游戏开发或其他性能敏感的应用程序需求而创建。尤其更适用于移动平台,这些平台上内存大小及带宽相比桌面系统都是受限的,而应用程序比如游戏又有更高的性能要求。它将序列化数据存储在缓存中,这些数据既可以存储在文件中,又可以通过网络原样传输,而不需要任何解析开销。

代码托管主页: https://github.com/google/flatbuffers

项目介绍主页: http://google.github.io/flatbuffers/index.html

 

二、FlatBuffers用途有哪些?

  1、对C++代码的序列化与反序列化:①写本地缓存,方便读取。②用于网络数据发送。

  2、将xml、json文件转换成二进制文件,大大缩减加载文件时间

用法

 关于FlatBuffers的用法,我下面还是通过代码向大家讲解,这样更直观,更容易理解。

 

复制代码
class Point
{
    float x;
    float y;
};

class Node
{

   std::string name;
   Point position;
};

class Layer
: public Node
{
   Node* friend;
   std::vector<Node*> children;
   std::vector<Point *> transform;
};
复制代码

1、使用前的准备

  首先构建一个schema文件。schema文件主要是记录了我们所要用的对象的成员信息。

 

//>>>>>>>>> schema begin <<<<<<<<<<<
namespace Layer; table Point_Fb { x:float;
  y:float;
} table Node_Fb { name:string;
  position:Point_Fb; }
table Layer_Fb
{
  super:Node_Fb;
  friend:Node_Fb;
  children:[Node_Fb];
  transform:[Point_Fb];
} root_type Layer_Fb;
//>>>>>>>>> schema end <<<<<<<<<<<
到这里我们的schema文件已经写完了,然后保存为
Layer_Fb.fbs文件。
然后下载google的flatbuffers的开源代码编译flatc.cpp得到flatc可执行文件,然后运行
flatc -c -o ./ ./Layer_Fb.fbs 生成一个Layer_Fb_generated.h的头文件,加到项目中。到这里,我们的准备工作就做完了。

注:

  1、flatbuffers的类型有很多我就没有一一列举了,大家可以在flatbuffers的文档里看到。
  2、schema文件中的除了table还有struct。区别就在于able是Flatbuffers中用来定义对象的主要方式,和struct最大的区别在于:它的每个字段都是可选的,而struct的所有成员都是required。 
    table除了成员名称和类型之外,还可以给成员一个默认值,如果不显式指定,则默认为0(或空)。struct不能定义scalar成员,比如说string类型的成员。在生成C++代码时,struct的成员顺序
    会保持和IDL的定义顺序一致,如果有必要对齐,生成器会自动生成用于对齐的额外成员。
    如果没有Layer中没有std::vector<Point*> tranform,那么这里我们的Point的定义可以是struct Point_Fb,因为我没有找到flatbuffers里面如何使用结构体数组的方法。(如果各位有找到还望不吝赐教)

2、具体使用方法

    1、序列化

    这里我有个对象就是auto layer = new Layer();如何序列化呢?

    我们就是要创建一个layer_Fb的对象,这个就是Layer对象对应的flatbuffers的对象,他包含了Layer对象的所有的信息。

    

复制代码
#include "Layer_Fb_generated.h"
    flatbuffers::FlatBufferBuilder builder_data;
    auto position_fb = CreatePoint_Fb(builder_data,layer.position.x,layer.position.y);
    auto super_fb = CreateNode_Fb(builder_data,builder_data.CreateString(layer.name),&position_fb);
    auto friend_fb = ...;
    
    std::vector<flatbuffers::Offset<Node_Fb>> Node_fbList;
    for (auto child : layer.children)
    {
        auto position_fb = CreatePoint_Fb(builder_data,child.position.x,child.position.y);
        auto child_fb = CreateNode_Fb(builder_data,builder_data.CreateString(child.name),&position_fb);
        Node_fbList.push_back(child_fb);
    }
    
    std::vector<flatbuffers::Offset<Point_Fb>> transformList;
    for (auto point : layer.transform)
    {
        auto position_fb = CreatePoint_Fb(builder_data,layer.position.x,position.y);
        transformList.push_back(position_fb);
    }
    
    auto layer_fb = CreateLayer_Fb(builder_data,position_fb,super_fb,friend_fb,Node_fbList,transformList);
//    auto layer_fb = CreateLayer_Fb(builder_data,
//                                   position_fb,
//                                   super_fb,
//                                   friend_fb,
//                                   Node_fbList.size() == 0 ? 0 : Node_fbList, //这样可以减少多余存储空间
//                                   transformList);
    builder_data.Finish(texture);
    
//    (char *)builder_data.GetBufferPointer(), builder_data.GetSize() 取得转换后的二进制文件。保存到本地或者用于网络传输
复制代码

  2、反序列化

    

auto layer_fb = flatbuffers::GetRoot<Layer_Fb>(builder_data.GetBufferPointer());//
    layer_fb->super/*schema 中的对象的名字*/();
    layer_fb->friend();
    layer_fb->children();
    layer_fb->transfrom();
  创建layer对象,对其一个个赋值就可以了。

注:
  这里并不是只能对schame中的root_type才能序列化,例如:你想只对Node_fb进行序列化,你就可以在得到node_fb对象的时候直接builder.finish(node_fb),返回利用
  flatbuffers::GetRoot<Node_Fb/*类型不要错咯*/>(builder_data.GetBufferPointer());方法一样可以

 

3、扩展

  那么如何对xml、json文件进行序列化呢?

  我的做法就是把xml、json文件解析成c++对象,然后序列化,保存到本地。然后就用保存的文件进行读取、反序列化操作。我对比过两中方式的读取效率。很明显读取flatbuffers文件后进行反序列化要比xml、json速度快6~10倍!但看这个值可能没感觉,当你解析一个xml可能用0.01s,但是解析flatbuffers文件你只要0.003秒。文件一多对比就会出来了。尤其是在手机游戏上的时候,启动和界面切换加载就会明显快好多。(如果你从事cocos2dx开发的话,你可以研究研究cocos的csb文件,其实就是一个flatbuffers文件。)    

 

谢谢各位的阅读!

各位有什么疑问可以直接在我的blog下留言或者是发送的我的个人邮箱[email protected]

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/linuxheik/article/details/77878683

智能推荐

图像线段检测几种方法_lines1, _, _, _ = lsd1.detect(gray_image1, 2, 2)-程序员宅基地

文章浏览阅读1.1k次。OpenCV-contrib有一个名为FastLineDetector的东西,如果它被用作LSD的替代品似乎很好。如果你有点感动,你会得到与LSD几乎相同的结果。当我将OpenCV提升到4.1.0时,LineSegmentDetector(LSD)消失了。_lines1, _, _, _ = lsd1.detect(gray_image1, 2, 2)

为什么人工智能用Python?-程序员宅基地

文章浏览阅读923次,点赞24次,收藏27次。Python 作为脚本语言,虽然上手简单、入门快,但是运行速度没有Java、C++快,应用也不够广泛,那Python到底有什么优势?来听听王道Python的主讲老师龙哥怎么说?Python被认为是一门相对容易学习和上手的编程语言,对初学者友好。其简洁的语法和清晰的代码结构使得开发人员能够更专注于解决问题而不是处理语法复杂性。这使得开发人员能够轻松地利用这些工具进行人工智能项目的开发。例如最流行的机器学习框架Scikit-learn只支持Python。

Python实例29:利用python自动创建多个Excel表格_python在excel表格内添加多张表-程序员宅基地

文章浏览阅读3k次,点赞4次,收藏19次。实例代码import xlwings as xwapp = xw.App(visible = True, add_book = False)for i in range(1, 21): workbook = app.books.add() workbook.save(f'e:\\example\\{i}班信息表.xlsx') workbook.close()app.quit()_python在excel表格内添加多张表

uni-app实现上拉加载,下拉刷新(下拉带动画)_uniapp 加载动画-程序员宅基地

文章浏览阅读5.7w次,点赞14次,收藏81次。直接代码展示了uni-app的上拉加载动画感觉还行,废话不多说了。。。1在pages.json添加允许下拉刷新{ "path":"pages/lookuser/lookuser", "style":{ "navigationBarTitleText":"用户日志", "enablePullDownRefresh": true//就是这个 }_uniapp 加载动画

常见服务器对jdk版本的支持_jdk 不支持国产服务器-程序员宅基地

文章浏览阅读2.6k次。WebSphere5.1:JDK1.4,Servelet2.3、JSP1.2WebSphere6.0:JDK1.4,Servelet2.4、JSP2.0WebSphere6.1:JDK5.0,Servelet2.4、JSP2.0Tomcat4.1:JDK1.4,Servelet2.3、JSP1.2Tomcat5.5:JDK5.0,Servelet2.4、JSP2.0_jdk 不支持国产服务器

mysql55dialect_关于数据库方言MySQLDialect、MySQL5Dialect、MySQL55Dialect、MySQL57Dialect、MySQL8Dialect之间的区别与联系...-程序员宅基地

文章浏览阅读657次。什么是Hibernate方言?Hibernate方言是用来告诉Hibernte如何对指定的数据库生成相应的SQL语句。尽管做了很多尝试去使SQL语句标准化,但是不同的数据库支持的SQL语句还是有很多不同的地方。所以Hibernate使用方言来辅助生成正确的SQL语句。①MySQLDialect②MySQL5Dialect③MySQL55Dialect④MySQL57Dialect⑤MySQL8Di..._mysql5dialect

随便推点

Linux 硬件时间(RTC time(2),热度飙升-程序员宅基地

文章浏览阅读229次,点赞4次,收藏6次。硬件时间,也被称为实时时钟(RTC),是指计算机主板上的一个独立于操作系统的设备,它在电源关闭甚至断电情况下也能保持运行。其功能是记录当前的日期和时间。系统时间是计算机内部使用的时间,它通常在启动时从RTC设置,然后由系统时钟进行跟踪。系统时钟是操作系统内核的一部分,可以以毫秒或纳秒级别提供精确时间。本地时间是系统时间经过时区转换后的时间。时区是根据地理位置确定的,全球分为24个时区,每个时区大约代表15度的经度。例如,北京时间是UTC+8,而伦敦时间是UTC+0。

〖产品思维训练白宝书 - 产品思维认知篇⑤〗- 学习 [产品思维] 需要做哪些准备?_产品思维学习-程序员宅基地

文章浏览阅读3.2w次,点赞45次,收藏30次。这一章节的目的是希望在正式的学习 "产品思维" 的知识点之前,让大家能够做好准备(包括心理准备与身体上的准备),整个准备过程也是参考的产品经理的闭环工作模式来设计的。_产品思维学习

uni-app 配置编译环境与动态修改manifest,2024年最新android基础面试题及答案-程序员宅基地

文章浏览阅读208次。但是这时候又碰到了一个问题。不同的网络环境,可能还需要配置不同的小程序appid。作为一个慵懒的程序员,根据不同的网络环境,手动去修改appid那是不可能的。【注意】:复制上述代码的时候,记得把备注删除。通过以上,根据不同的编译方式,可以自动的切换不同的网络环境。重要事情说三遍(可视化创建的项目,在项目的根目录下)。二、动态修改manifest.json参数。动态配置appid,本质就是要动态配置。由以上可知,需要修改的是。1、创建如下项目结构配置。3、对应网络环境域名配置。

a33 linux 硬解码_全志A33-Linux软硬件定制-程序员宅基地

文章浏览阅读234次。佣金是参考 具体贵方评估说明:我司现有一款产品需求定制产品主板部分的硬件及系统,产品硬件PCB分两个部分:主板及电源板,电源板我司已经定型,现将主板及系统软件外包,由于我方产品外形已经定型,需求根据我方提供的外形尺寸及布局参考定制主板,时间周期尽量要快,1个月之内。交付硬件设计资料(原理图,PCB图等)软件源码资料(uBoot kernel Roofs等资料)以及符合要求的硬件主板5块。硬件需求:..._全志硬解码库例程

JSP及语法概要 (山无言) _jsp303 @digits-程序员宅基地

文章浏览阅读1.6k次。JSP及语法概要 (山无言) 有一点别搞混了~!到现在还有不明白的就是javascript与java编程语言是不一样的!  JavaServer Pages(JSP)使得我们能够分离页面的静态HTML和动态部分。HTML可以用任何通常使用的Web制作工具编写,编写方式也和原来的一样;动态部分的代码放入特殊标记之内,大部分以“<%”开始,以“%>”结束。例如,下面是一个JSP页面的片断_jsp303 @digits

中兴B860AV2.1U_非高安_晶晨S905LB处理器_8189无线_线刷固件包-程序员宅基地

文章浏览阅读1.8k次。2、电脑上安装好刷机工具Amlogic USB Burning Tool 软件 →打开软件 →文件 →导入烧录包 →把【擦除flash】和【擦除bootloader】两项勾选先默认去掉(如不识别或进度条不走再打勾刷机) →点击【开始】 →盒子接电源线 →电源关闭 →把USB线一端插上盒子 →保持短接 →USB另一端插上电脑 →通电开机。_b860av2.1u

推荐文章

热门文章

相关标签