flatbuffer 实例之 builder
example_builder.h
#ifndef EXAMPLE_BUILDER_H
#define EXAMPLE_BUILDER_H
/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */
#ifndef EXAMPLE_READER_H
#include "example_reader.h"
#endif
#ifndef FLATBUFFERS_COMMON_BUILDER_H
#include "flatbuffers_common_builder.h"
#endif
#include "flatcc/flatcc_prologue.h"
#ifndef flatbuffers_identifier
#define flatbuffers_identifier 0
#endif
#ifndef flatbuffers_extension
#define flatbuffers_extension ".bin"
#endif
static const flatbuffers_voffset_t __wii_Packet_required[] = { 0 };
typedef flatbuffers_ref_t wii_Packet_ref_t;
static wii_Packet_ref_t wii_Packet_clone(flatbuffers_builder_t *B, wii_Packet_table_t t);
__flatbuffers_build_table(flatbuffers_, wii_Packet, 3)
#define __wii_Packet_formal_args , int32_t v0, flatbuffers_bool_t v1, flatbuffers_string_ref_t v2
#define __wii_Packet_call_args , v0, v1, v2
static inline wii_Packet_ref_t wii_Packet_create(flatbuffers_builder_t *B __wii_Packet_formal_args);
__flatbuffers_build_table_prolog(flatbuffers_, wii_Packet, wii_Packet_file_identifier, wii_Packet_type_identifier)
__flatbuffers_build_scalar_field(0, flatbuffers_, wii_Packet_a, flatbuffers_int32, int32_t, 4, 4, INT32_C(0), wii_Packet)
__flatbuffers_build_scalar_field(1, flatbuffers_, wii_Packet_b, flatbuffers_bool, flatbuffers_bool_t, 1, 1, UINT8_C(0), wii_Packet)
__flatbuffers_build_string_field(2, flatbuffers_, wii_Packet_c, wii_Packet)
static inline wii_Packet_ref_t wii_Packet_create(flatbuffers_builder_t *B __wii_Packet_formal_args)
{
if (wii_Packet_start(B)
|| wii_Packet_a_add(B, v0)
|| wii_Packet_c_add(B, v2)
|| wii_Packet_b_add(B, v1)) {
return 0;
}
return wii_Packet_end(B);
}
static wii_Packet_ref_t wii_Packet_clone(flatbuffers_builder_t *B, wii_Packet_table_t t)
{
__flatbuffers_memoize_begin(B, t);
if (wii_Packet_start(B)
|| wii_Packet_a_pick(B, t)
|| wii_Packet_c_pick(B, t)
|| wii_Packet_b_pick(B, t)) {
return 0;
}
__flatbuffers_memoize_end(B, t, wii_Packet_end(B));
}
#include "flatcc/flatcc_epilogue.h"
#endif /* EXAMPLE_BUILDER_H */
这里面主要就是定义了两个函数,wii_Packet_create(创建)与wii_Packet_clone(克隆/复制)。
其中wii_Packet_create函数的参数__wii_Packet_formal_args仔细看一下。
#define __wii_Packet_formal_args , int32_t v0, flatbuffers_bool_t v1, flatbuffers_string_ref_t v2
其实就是Packet表中的三个变量
- v0(int32_t)对应变量a(int),这个对应很清楚。
- v1(flatbuffers_bool_t)对应变量b(bool),这其中的flatbuffers_bool_t的实际定义是
typedef uint8_t flatbuffers_bool_t
- v2(flatbuffers_string_ref_t)对应变量c(string),其中的flatbuffers_string_ref_t的实际定义是
typedef flatcc_builder_ref_t flatbuffers_string_ref_t typedef flatbuffers_soffset_t flatcc_builder_ref_t; typedef int32_t flatbuffers_soffset_t
我们来试着创建一个流
#include <stdio.h>
#include <stdlib.h>
#include "hexdump.h"
#include "example_builder.h"
int main(int argc, char* argv[])
{
char *dbuf;
size_t dsize;
flatcc_builder_t builder;
flatcc_builder_init(&builder);
int a = 88;
flatbuffers_bool_t b = flatbuffers_true;
flatbuffers_string_ref_t c = flatbuffers_string_create_str(&builder, "hello!!");
printf("a=0x%x b=%d c=%d\n", a, b, c);
wii_Packet_create(&builder, a, b, c);
dbuf = flatcc_builder_finalize_buffer(&builder, &dsize);
hexdump("Packet", dbuf, dsize, stderr);
flatcc_builder_free(dbuf);
flatcc_builder_clear(&builder);
return 0;
}
flatbuffer编码的内存结构主要搞清楚两个
- object / Packet就是一个object
int32:offset_vtable [fields]
- vtable
uint16:vtable_size uint16:object_size [uint16:offset_field]
分析这个实例的内在结构
$ ./build/fbproject
a=0x58 b=1 c=-12
dbuf=0x55fd1085b620 dsize=38
Packet:
00000000 e4 ff ff ff 58 00 00 00 08 00 00 00 01 00 00 00 |....X...........|
-----------
offset_vtable
-----------
a_var=88
-----------
c_offset=8
--
b_var=1
-------
这3个字节是为了对齐
00000010 07 00 00 00 68 65 6c 6c 6f 21 21 00 0a 00 0d 00 |....hello!!.....|
----------- ------------------------
c_len=7 c_str="hello!!"
|vtable
-----
vtable_size=10
-----
object_size=13
00000020 04 00 0c 00 08 00 |......|
-----
a_offset=4
-----
b_offset=12
-----
c_offset=8
这里有一个问题是a、b、c三个变量的类型是如何区分的,特别是string类型。这块实际是代码中写死的,并不在内存中展示,也就是说如果不知道fbs结构的情况下是很难解析出原始值的。