FlatBuffer 学习笔记

357 阅读2分钟

与ProtoBuf类似,这是一种序列化工具,把编程语言的数据结构转成二进制内容,保存到文件中(ProtoBuf网络传输),以及方便地从文件中再次恢复。

Write your own schema(.fbs)

// Example IDL file for our monster's schema.

namespace MyGame.Sample;

enum Color:byte { Red = 0, Green, Blue = 2 }

union Equipment { Weapon } // Optionally add more tables.

struct Vec3 {
  x:float;
  y:float;
  z:float;
}

table Monster {
  pos:Vec3;
  mana:short = 150;
  hp:short = 100;
  name:string;
  friendly:bool = false (deprecated);
  inventory:[ubyte];
  color:Color = Blue;
  weapons:[Weapon];
  equipped:Equipment;
  path:[Vec3];
}

table Weapon {
  name:string;
  damage:short;
}

root_type Monster;

  • enum, union, struct这些都会与C语言概念一一对应
  • table有所不同(struct 有稳定的结构,数据inline保存) 通过生成的c代码可以看到,table结构体几乎没有成员变量,不占用空间,数据通过偏移保存。
  • root_type 标识主结构体

注意:当一个个object填入Binary的顺序是逆序的,也就是最先创建的Object位于Binary的最后面,Object里面具体的内容是顺序填充的。

Generate C header from above schema

运行以下命令会自动生成monster_generated.h文件

flatc --cpp C:\Users\glu\Desktop\flatbuffers\samples\monster.fbs

Write to flatBuffer

create a vector of nested objects

例如:tables, strings, vectors 这都都是间接存储的,vector里面存的是偏移值。

不能直接使用string,vector等去构建某个对象,需要通过offset对象去构建,因此先通过create函数去创建offset对象。

Offset<String> CreateString(const char *str)
Offset<Vector<T>> CreateVector(const std::vector<T, Alloc> &v)
  1. 创建各自的offset
  2. offset存入std::vector 示例代码如下
// Place the weapons into a `std::vector`, then convert that into a FlatBuffer `vector`.
std::vector<flatbuffers::Offset<Weapon>> weapons_vector;
weapons_vector.push_back(sword);
weapons_vector.push_back(axe);
auto weapons = builder.CreateVector(weapons_vector);

create a vector of common objects

例如:struct, 标量等,这些都是直接存储的(inline)

如果tables等也以这种方式存储,程序会报错。

Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) };
auto path = builder.CreateVectorOfStructs(points, 2);

the other optional way(convenient )

// You can use this code instead of `CreateMonster()`, to create our orc
// manually.
MonsterBuilder monster_builder(builder);
monster_builder.add_pos(&position);
monster_builder.add_hp(hp);
monster_builder.add_name(name);
monster_builder.add_inventory(inventory);
monster_builder.add_color(Color_Red);
monster_builder.add_weapons(weapons);
monster_builder.add_equipped_type(Equipment_Weapon);
monster_builder.add_equipped(axe.Union());
auto orc = monster_builder.Finish();

get the buffer

uint8_t *buf = builder.GetBufferPointer();
int size = builder.GetSize(); // Returns the size of the buffer that
                              // `GetBufferPointer()` points to.

Read from flatBuffer

Mutating flatBuffer

支持局部修改flatBuffer,避免了再次生成整个Buffer.

auto monster = GetMutableMonster(buffer_pointer);  // non-const
monster->mutate_hp(10);                      // Set the table `hp` field.
monster->mutable_pos()->mutate_z(4);         // Set struct field.
monster->mutable_inventory()->Mutate(0, 1);  // Set vector element.

JSON

.fbs 文件描述了二进制文件的结构/格式,通过代码进行添加具体内容,再通过代码读取具体的内容。

这里支持将具体的文件内容放到json里面,支持二进制与json文件的相互转换。

# Json ---> Binary
flatc --binary monster.fbs monsterdata.json

# Binary ---> Json
flatc --json --raw-binary monster.fbs -- monsterdata.bin

Reference: google.github.io/flatbuffers…