Reflection for nested data type

756 views
Skip to first unread message

Hải Nguyễn

unread,
Nov 18, 2015, 4:45:26 AM11/18/15
to FlatBuffers
Hi,
I am newbie to Flatbuffers. So I am sorry for any misunderstanding.
I am trying to experiment idea of locating the data field by its name, aka reflection.
From example (test.cpp), it seems that we can only lookup field by name for one level. For eg, back to monster example
struct Vec3 (force_align: 16) {
  x:float;
  y:float;
  z:float;
  test1:double;
  test2:Color;
  test3:Test;
}

table Stat {
  id:string;
  val:long;
  count:ushort;
}

/// an example documentation comment: monster object
table Monster {
  pos:Vec3 (id: 0);
  hp:short = 100 (id: 2);
}

It is possible to access hp field of Monster, however we cannot access x of Vec3 of Monster (using notation like this: "pos.x"). 
Is it possible to perform something like this: looking up a child field of a struct of a table?
Thank you.

mikkelfj

unread,
Nov 18, 2015, 2:04:51 PM11/18/15
to FlatBuffers
All types are defined at top level in terms of primitive types and other types also defined at top-level.
So once you learn a member is a complex type, you can look up that type separately.
In your example you first learn that pos is of type Vec3, then you forget about Monster and look up x in the Vec3 type at top-level.

Note: I am only speaking about how the reflection schema is defined - you can always read a binary schema as I described.
Each language may or may not have helpers to simplify reflection lookup recursively, or you can easily write your own lookup routine to parse a dotted string and do the lookups.

Wouter van Oortmerssen

unread,
Nov 20, 2015, 3:38:38 PM11/20/15
to mikkelfj, FlatBuffers
Yup, like Mikkel said, you have to look up the type of the sub-object, and then you can look up the field x in that.

--
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.

Hải Nguyễn

unread,
Nov 22, 2015, 9:02:13 PM11/22/15
to FlatBuffers, mik...@dvide.com
Thank Mikkel and Wouter, 
I thought about recursive way like this before, however I hope there is maybe a better way to lookup the sub-field within table directly.
/Hai.

Zarian Waheed

unread,
Jan 15, 2016, 9:01:05 PM1/15/16
to FlatBuffers
I was trying to use reflection functionality, but I got stuck on one place. Here is some code for recursively traversing fields of a table using reflection (assume there is an outside code that calls this function for each root level field of type reflection::Obj):

void RecursiveReflection(const flatbuffers::Tabletableconst reflection::ObjectreflectionTableconst reflection::Schemaschema) {  
  auto tableFields = reflectionTable->fields();
  for (size_t i = 0; i < tableFields->Length(); i++) {
    if (tableFields->Get(i)->type()->base_type() == reflection::Obj) {
      flatbuffers::Table* t = flatbuffers::GetFieldT(*table, *tableFields->Get(i));

      std::string typeName; // How to get the type name here

      const reflection::Object* refT = schema->objects()->LookupByKey(typeName);

      RecursiveReflection(t, refT, schema);
    }
    std::string fieldName = tableFields->Get(i)->name()->c_str();
    auto fieldVal = flatbuffers::GetAnyFieldS(*table, *tableFields->Get(i), schema);    
  }
}


How can I get the name of the nested table type (not the field name but the type name). Reflection::Type doesn't seem to have the type name, it just has the field name field type (e.g. INT, FLOAT etc.) 

Zarian Waheed

unread,
Jan 19, 2016, 4:05:04 PM1/19/16
to FlatBuffers
Ok I figured out how to get to the nested table, thought I would share that so others may benefit. Inside reflection.fbs you will find:

table Type {
    base_type:BaseType;
    element:BaseType = None;  // Only if base_type == Vector.
    index:int = -1;  // If base_type == Object, index into "objects" below.
                     // If base_type == Union, UnionType, or integral derived
                     // from an enum, index into "enums" below.
}

"index" field points to the array index of vector "objects" in "schema" table:

table Schema {
    objects:[Object] (required);  // Sorted.
    enums:[Enum] (required);      // Sorted.
    file_ident:string;
    file_ext:string;
    root_table:Object;
}

The function I shared earlier would change to::

void RecursiveReflection(const flatbuffers::Tabletableconst reflection::ObjectreflectionTableconst reflection::Schemaschema
) {  
  if (table == nullptrreturn;
  auto tableFields = reflectionTable->fields();
  for (size_t i = 0; i < tableFields->Length(); i++) {
    if (tableFields->Get(i)->type()->base_type() == reflection::Obj) {
      flatbuffers::Table* t = flatbuffers::GetFieldT(*table, *tableFields->Get(i));
      const reflection::Object* refT = schema->objects()->Get(tableFields->Get(i)->type()->index());
}

Reply all
Reply to author
Forward
0 new messages