C++ reference another flatbuffer

173 views
Skip to first unread message

Stuart McDonald

unread,
Apr 12, 2018, 8:22:30 AM4/12/18
to FlatBuffers

Hi,
    I'd like to have a flatbuffer with the ability to values in another flatbuffer. This is so I can have defaults/globals/whatever you want to call them e.g. (I know the following isn't valid, it's to try and explain what I'm trying to do)

Globals.fbs
// Just a table of some values I want to define various globals for
table
ValuesTB {
    v1
:int;
    v2
:int;
    v3
:int;
}
// The table of different globals I want to reference
table
GlobalsTB {
   global1
: ValuesTB;
   global2
: ValuesTB;
   
..etc.
}
root_type
GlobalsTB;


Data.fbs
include "Globals.fbs"
// A single Data entry. This can have it's own ValuesTB in 'values' or can reference a global value via 'valuesRef'
table
DataTB {
    values
: ValuesTB;
    valuesRef
: int (hash: "fnv1_32"); // Not correct, but I think I need to use a hash somehow
}

table
TheData {
  thedData
: [DataTB];
}

root_type
TheData;

Data.json
{
   theData
: [
           
{ values: { v1:1, v2:42, v3:99 } },
           
{ valueRef: "global1" },  // Again, not correct. Just to show I somehow want to
           
{ valueRef: "global1" },  // reference a "ValuesTB" defined "globally"
           
{ valueRef: "global3" },
           
{ values: { v1:77, v2:77, v3:77 } },
           
{ valueRef: "global1" },
           
]
}



I've read the part on using a hash and a resolver, but I can't work out what I should be doing (assuming that's the correct way).

Thanks,
Stuart.



Wouter van Oortmerssen

unread,
Apr 12, 2018, 4:50:23 PM4/12/18
to a.stuart...@gmail.com, FlatBuffers
Yes, we do have a facility for this, and you are going in the right direction with this.
Do note that this only works for the object API (creating an actual pointer to your globals), not in the base API.
There is no prescribed way how to do this. The resolver is on purpose open-ended: it is up to you how to implement it. Typically, you would read your globals object, create your own lookup table from names to pointers, then load the second buffer, and while unpacking to the object API, the resolver turns names (hashes) into pointers on the fly.

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

mikkelfj

unread,
Apr 12, 2018, 5:10:34 PM4/12/18
to FlatBuffers
The C api (FlatCC) recentluy added clone and pick.

This allows you to clone a table from a finished buffer into a field referencing a table of same type.
It doesn't do just some of the fields, but this can be done by calling pick one field at time (clone is a wrapper that picks all the fields from the other table).

There is also some discussion of a clone_into facility where more fields can be added before or after the clone so the first to update the field wins, but this is not currently implemented.

Stuart McDonald

unread,
Apr 16, 2018, 4:26:43 AM4/16/18
to FlatBuffers
Ahh I see. Thanks. I don't use the object API so I've just gone with the simple idea of storing a map of name -> table offset. e.g. (just posting to hoping add some more value to this thread).

class GlobalData
{
public:
   
typedef std::map<std::string, flatbuffers::voffset_t> Lookup;

   
template<typename T>
   
const T* get(const std::string& name) const {
       
auto find = mLookup.find(name);
       
return (find != mLookup.end())
           
? mRoot->GetPointer<const T*>(find->second)
           
: nullptr;
   
}
private
   
const Lookup& mLookup;
   
const flatbuffers::Table* mRoot;
};



And
    GlobalData::Lookup lookup;
    lookup
["global1"] = Globals::VT_GLOBAL1;
    lookup
["global2"] = Globals::VT_GLOBAL2;
    lookup
["global3"] = Globals::VT_GLOBAL3;

   
auto g1 = globals.get<ValuesTB>("global1");


Populating the lookup table could be auto-generated, but I'm keeping it simple until I have more than one use case. I don't need nested data so flat table access is fine.

Reply all
Reply to author
Forward
0 new messages