接上文

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编码的内存结构主要搞清楚两个

  1. object / Packet就是一个object
      int32:offset_vtable
      [fields]
    
  2. 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结构的情况下是很难解析出原始值的。