FlatBuffers提供的Schemas (又叫IDL, Interface Definition Language) 语法在于c-like, 无论对于C语言用户还是其它IDL用户来说都很容易掌握。

引用官方提供的IDL例子代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// example IDL file

namespace MyGame;

enum Color : byte { Red = 1, Green, Blue }

union Any { Monster, Weapon, Pickup } // Weapon和Pickup不在该例子中定义

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

table Monster {
pos:Vec3;
mana:short = 150;
hp:short = 100;
name:string;
friendly:bool = false (deprecated, priority: 1);
inventory:[ubyte];
color:Color = Blue;
test:Any;
}

root_type Monster;

table && struct

table是Flatbuffers中用来定义对象的主要方式,和struct最大的区别在于:它的每个字段都是可选的(类似protobuf中的optional字段)。而struct的所有成员都是required.

table除了成员名称和类型之外,还可以给成员一个默认值,如果不显式指定,则默认为0(或空)。
struct不能定义scalar成员,比如说string类型的成员。在生成C++代码时,struct的成员顺序会保持和IDL的定义顺序一致,如果有必要对齐,生成器会自动生成用于对齐的额外成员。如以下IDL代码:

1
2
3
4
5
6
struct STest
{
a : int;
b : int;
c : byte;
}

在生成为C++代码之后,会补充两个用于padding的成员padding0与padding1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
MANUALLY_ALIGNED_STRUCT(4) STest {
private:
int32_t a_;
int32_t b_;
int8_t c_;
int8_t __padding0;
int16_t __padding1;

public:
STest(int32_t a, int32_t b, int8_t c)
: a_(flatbuffers::EndianScalar(a)), b_(flatbuffers::EndianScalar(b)), c_(flatbuffers::EndianScalar(c)), __padding0(0) {}

int32_t a() const { return flatbuffers::EndianScalar(a_); }
int32_t b() const { return flatbuffers::EndianScalar(b_); }
int8_t c() const { return flatbuffers::EndianScalar(c_); }
};
STRUCT_END(STest, 12);

table的成员顺序是动态调整的,这和struct有区别。在生成C++代码时,生成器会自动调整为最佳顺序以保证它占用最小的内存空间。

关于comment技巧

我们知道用”//“可以在IDL中对文本进行注释以便增加可读性。其实还有一种在生成后的代码中增加注释的方法,就是用”///“。如IDL代码:

1
2
3
4
5
6
7
/// test structure
struct STest
{
a : int;
b : int;
c : byte;
}

生成的C++代码会自动加入注释:

1
2
3
4
5
6
/// test structure
MANUALLY_ALIGNED_STRUCT(4) STest {
private:
int32_t a_;

// ...

Reference : http://google.github.io/flatbuffers/md__schemas.html