inner tables must be built first?

59 views
Skip to first unread message

Peter Lesslie

unread,
May 31, 2016, 10:54:13 AM5/31/16
to FlatBuffers
I am new to flatbuffers, and I assume that I'm doing something wrong, but I was definitely surprised by the following behavior.  

I was looking at how the buffers are formatted on the wire and had a schema like:
table Inside {
      b
:string;
      c
:string;
}

table
Object {
      a
:string;
      i
:Inside;
      d
:string;
}

root_type
Object;
file_identifier
"OBJT";

I was surprised that when I built Object in order, the "a" element was lost:
    using namespace flatbuffers;
   
FlatBufferBuilder fbb;
   
ObjectBuilder ob(fbb);
   
    ob
.add_a(fbb.CreateString("A"));
   
   
InsideBuilder ib(fbb);
    ib
.add_b(fbb.CreateString("B"));
    ib
.add_c(fbb.CreateString("C"));
    ob
.add_i(ib.Finish());
   
    ob
.add_d(fbb.CreateString("D"));

   
FinishObjectBuffer(fbb, ob.Finish());

    // code below this point will be the same for all examples

   
const uint8_t *buf = fbb.GetBufferPointer();
   
const size_t size = fbb.GetSize();
   
    Verifier verifier(buf, size);
   
if (!VerifyObjectBuffer(verifier)) {
       
throw std::runtime_error{"Invalid buffer!"};
   
}


   
// macro to make it easier to print the flatbuffer::String objects
   
#define PP(str) str ? str->c_str() : "empty"
   
const Object *obj = GetObject(buf);
   
if (obj) {
        printf
("A = %s\n", PP(obj->a()));
       
if (obj->i()) {
            printf
("B = %s\n", PP(obj->i()->b()));
            printf
("C = %s\n", PP(obj->i()->c()));
       
} else {
            printf
("Inner struct missing\n");
       
}
        printf
("D = %s\n", PP(obj->d()));
   
} else {
        printf
("Object missing\n");
   
}

Output:
A = empty
B = B
C = C
D = D

If I move the add_a() line to after adding i then it works:
    FlatBufferBuilder fbb;
   
ObjectBuilder ob(fbb);
   
InsideBuilder ib(fbb);
    ib
.add_b(fbb.CreateString("B"));
    ib
.add_c(fbb.CreateString("C"));
    ob
.add_i(ib.Finish());
    ob
.add_a(fbb.CreateString("A"));
    ob
.add_d(fbb.CreateString("D"));
   
FinishObjectBuffer(fbb, ob.Finish());

Output:
A = A
B = B
C = C
D = D

If add a and d first, then I lose both of the elements:
    FlatBufferBuilder fbb;
   
ObjectBuilder ob(fbb);
    ob
.add_a(fbb.CreateString("A"));
    ob
.add_d(fbb.CreateString("D"));
   
InsideBuilder ib(fbb);
    ib
.add_b(fbb.CreateString("B"));
    ib
.add_c(fbb.CreateString("C"));
    ob
.add_i(ib.Finish());
    FinishObjectBuffer(fbb, ob.Finish());

Output:
A = empty
B = B
C = C
D = empty


This behavior is fine, but I didn't see it documented anywhere, and it is a little strange that the verifier returns true on this buffer (though it is true that this buffer can be read safely).  So, is this intended behavior, or I am doing something wrong?

-Peter

Wouter van Oortmerssen

unread,
May 31, 2016, 2:21:22 PM5/31/16
to Peter Lesslie, FlatBuffers
Yes, you can't nest creation of tables / strings / vectors. Are you using the latest version of FlatBuffers? Or only in release mode? This code should normally generate an assert alerting you that you shouldn't use nesting.

Correct code looks something like:

    FlatBufferBuilder fbb;

    auto sa = fbb.CreateString("A");
    auto sb = fbb.CreateString("B");
    auto sc = fbb.CreateString("C");
    auto sd = fbb.CreateString("D");

    InsideBuilder ib(fbb);
    ib.add_b(sb);
    ib.add_c(sc);
    auto io = ib.Finish();

    ObjectBuilder ob(fbb);
    ob.add_a(sa);
    ob.add_i(io);
    ob.add_d(sd);

    FinishObjectBuffer(fbb, ob.Finish());



--
You received this message because you are subscribed to the Google Groups "FlatBuffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flatbuffers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Peter Lesslie

unread,
May 31, 2016, 2:43:46 PM5/31/16
to FlatBuffers, pcle...@gmail.com
Makes sense, I was running in release mode so I was missing the asserts.  Thanks for the help.

-Peter
Reply all
Reply to author
Forward
0 new messages