Carpe Diem

備忘録。https://github.com/jun06t

FlatBuffers を使ってみる2

今度はネストしたテーブルを使ってみます。 ネストしないシンプルなテーブルに比べてちょこちょこ落とし穴があるのでご注意下さい。

 

◆例1(テーブルのみの場合)

こちらは簡単です。以下のように作ります。

・メインテーブル:Parent

・サブテーブル:Child1, 2, 3

 

定義ファイルは以下のように作成します。

hoge.fbs

namespace test;

table Child1 {
  param1_1:string;
  param1_2:int;
}

table Child2 {
  param2_1:string;
  param2_2:bool;
}

table Child3 {
  param3_1:string;
  param3_2:float;
}

table Parent {
  id:int;
  cld1:Child1;
  cld2:Child2;
  cld3:Child3;
}

root_type Parent;

 

◆オブジェクトの作成順、データのセット順

①builderインスタンスをNew

②Child1をStart→値セット→End

③Child2をStart→値セット→End

④Child3をStart→値セット→End

⑤ParentをStart→Child1,2,3をセット→End

⑥Finish で完了です。

 

◆サンプルコード

package main

import (
        "fmt"

        "github.com/google/flatbuffers/go"

        "./test"
)

func main() {
        b := flatbuffers.NewBuilder(0)

        test.Child1Start(b)
        test.Child1AddParam11(b, b.CreateString("child1"))
        test.Child1AddParam12(b, 10)
        child1 := test.Child1End(b)

        test.Child2Start(b)
        test.Child2AddParam21(b, b.CreateString("child2"))
        test.Child2AddParam22(b, 0)
        child2 := test.Child2End(b)

        test.Child3Start(b)
        test.Child3AddParam31(b, b.CreateString("child3"))
        test.Child3AddParam32(b, 100)
        child3 := test.Child3End(b)

        test.ParentStart(b)
        test.ParentAddCld1(b, child1)
        test.ParentAddCld2(b, child2)
        test.ParentAddCld3(b, child3)
        parent := test.ParentEnd(b)

        b.Finish(parent)

        obj := test.GetRootAsParent(b.Bytes, b.Head())
        rch1 := new(test.Child1)
        rch1 = obj.Cld1(rch1)
        fmt.Println(rch1.Param11())

        rch2 := new(test.Child2)
        rch2 = obj.Cld2(rch2)
        fmt.Println(rch2.Param21())

        rch3 := new(test.Child3)
        rch3 = obj.Cld3(rch3)
        fmt.Println(rch3.Param31())
}

 

◆実行

$ go run test.go
child1
child2
child3

 

◆例2(Structもある場合)

Structがあるとちょっと面倒です。以下のように作ります。

・メインテーブル:Parent

・サブテーブル:T1

・Struct:S1 hoge.fbs

namespace test;

table T1 {
  param1:string;
  param2:int;
}

struct S1 {
  param1:int;
  param2:bool;
}

table Parent {
  obj1:T1;
  obj2:S1;
}

root_type Parent;

 

◆オブジェクトの作成順、データのセット順

①builderインスタンスをNew

②T1をStart→値セット→End

③ParentをStart

④T1をParentにセット

⑤S1をParentの中で作成→Parentにセット

⑥ParentをEnd

⑦Finish です。

ポイントは⑤です。Structは作成後すぐにセットして下さい。 作成する場所とセットする場所が離れていると怒られます。

 

◆サンプルコード

package main

import (
        "fmt"

        "github.com/google/flatbuffers/go"

        "./test"
)

func main() {
        b := flatbuffers.NewBuilder(0)

        test.T1Start(b)
        test.T1AddParam1(b, b.CreateString("table 1"))
        test.T1AddParam2(b, 10)
        obj1 := test.T1End(b)

        test.ParentStart(b)
        test.ParentAddObj1(b, obj1)

        obj2 := test.CreateS1(b, 10, 0)
        test.ParentAddObj2(b, obj2)

        parent := test.ParentEnd(b)

        b.Finish(parent)

        res := test.GetRootAsParent(b.Bytes, b.Head())
        resObj1 := new(test.T1)
        resObj1 = res.Obj1(resObj1)
        fmt.Println(resObj1.Param1())

        resObj2 := new(test.S1)
        resObj2 = res.Obj2(resObj2)
        fmt.Println(resObj2.Param1())
}

 

実行

$ go run test.go
table 1
10

 

◆よく見るエラー

non-inline data write inside of object

Start して End せずにもう一度中で Start すると置きます。

inline data write outside of object

struct の作成場所がおかしいです。 大抵作ってすぐに Add してあげれば通ります。

index out of range

Start する前に Add とかしてアクセスしようとすると置きます。ちゃんと Start しましょう。