Hi,
I want to use flatbuffers which contain flatbuffers inside. The use case is a messaging library, which wraps any datatype inside a flatbuffer as a payload:
// message.fbs
namespace Lib;
enum Type : byte { Request, Reply }
table Header {
type:Type = Request;
timestamp:uint = 0;
datatype:uint;
}
table Message {
header:Header;
payload:[ubyte];
}
root_type Message;
The messaging library does not no at compile time which datatypes will be contained in its payload (so I can't use a union).
I tried the following code with some simple demo datatypes:
// app1.fbs
namespace App1;
table SomeDataType {
value:uint = 123;
}
root_type SomeDataType;
// app2.fbs
namespace App2;
table Data {
text:string;
}
root_type Data;
// demo.cpp
#include <iostream>
#include "flatbuffers/flatbuffers.h"
#include "app1_generated.h"
#include "app2_generated.h"
#include "message_generated.h"
int main(int argc, char* argv[])
{
flatbuffers::FlatBufferBuilder fbb;
// create app data
int sentDataType = std::stoi(argv[1]);
if (sentDataType == 1)
{
auto sdt = App1::CreateSomeDataType(fbb, 555);
fbb.Finish(sdt);
}
else if(sentDataType == 2)
{
auto text = fbb.CreateString("foo");
auto data = App2::CreateData(fbb, text);
fbb.Finish(data);
}
// create wrapper message
auto payload = fbb.CreateVector(fbb.GetBufferPointer(), fbb.GetSize());
auto header = Lib::CreateHeader(fbb, Lib::Type_Request, 456, sentDataType);
fbb.Finish(header);
Lib::MessageBuilder msg(fbb);
msg.add_header(header);
msg.add_payload(payload);
auto msgLoc = msg.Finish();
fbb.Finish(msgLoc);
// ... transmit to receiver ...
auto recvMsg = Lib::GetMessage(fbb.GetBufferPointer());
// dynamically determine the datatype inside payload
auto recvDataType = recvMsg->header()->datatype();
if (recvDataType == 1)
{
auto recvSdt = App1::GetSomeDataType(recvMsg->payload()->Data());
std::cout << recvSdt->value() << std::endl;
}
else if (recvDataType == 2)
{
auto recvData = App2::GetData(recvMsg->payload()->Data());
std::cout << recvData->text()->str() << std::endl;
}
return 0;
}
$ ./demo 1
555
$ ./demo 2
foo
I have several questions about my approach:
Is my approach valid?
Is there a more "native flatbuffers-style" way to solve this?
?
Can the copy happening at
fbb.CreateVector(fbb.GetBufferPointer(), fbb.GetSize()); be avoided?
Thanks for your reply.
I am not sure I understand you correctly. Do you think I use a string for storing the payload? I thought payload:[ubyte]; meant a vector of bytes.
Why would the buffer I get through fbb.GetBufferPointer() and store inside the payload need to have any special alignment treatment inside Message?
What do you mean by "cast to flatbuffer type"? I pass the payload buffer to flatbuffers using e.g. App1::GetSomeDataType(recvMsg->payload()->Data());
Is this the correct approach?
--
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.