I have come across the oneof
field concept while building grpc services definition (C++ server/client). However, in gRPC web page, I couldn't find proper documentation of oneof
usage (write and read operation), any lead on this will be really helpful.
Looking at grpc generated code for Services.proto
, it's hard to understand which are usable public methods. Although, I could find - set_status() is there for setting StatusCode.status
field and but couldn't find similar set_myfoo() or set_mybar() methods.
Service.proto
message Foo {
required uint32 id = 1;
}
message Bar {
required uint32 aID = 1;
required bytes metadata = 3;
required bytes payload = 4;
}
message ServiceMessageRequest {
required uint32 status = 1;
oneof data {
Foo myfoo = 2;
Bar mybar = 3;
}
}
how these oneof
fields - ServiceMessageRequest.data.myfoo
and ServiceMessageRequest.data.mybar
and thier metadata/payload field can be set?
Short Answer :
mutable_*
or set_allocated_*
methods, but there is a catch !!
- when using
set_allocated_*
then memory management should be handled by developer and memory should be dynamically allocated on heap (local variables cause double free and segmentation issues) - check this answer- when using
mutable_*
then gRPC will take care of memory management. Thus, it's an easier and preferred option. - check this answer
Detailed Explanation :
For better understanding, assume a simple string
type str is added in ServiceMessageRequest
(from original question) : [Now it has both basic and complex types in oneof data]
message ServiceMessageRequest {
required uint32 status = 1;
oneof data {
string str = 2;
Foo myfoo = 3;
Bar mybar = 4;
}
}
Setting oneof fields can be straight forward (as below), if they are simple types - integer/string
etc. protobuff
compiler generates the respective setter/getter for it.
ServiceMessageRequest msg;
msg.set_status(1);
msg.set_str("string"); //setting oneof field
However, if oneof
fields have sub structures (or some may call "sub-messages"), then they are set slightly differently (as below) :
ServiceMessageRequest msg;
msg.set_status(10);
msg.set_str("oneof string"); //setting oneof field
// there is no need to release myfoo, it will be released by gRPC.
Foo* myfoo = msg.mutable_myfoo(); //set oneof as myfoo
myfoo->set_id(20); //set the sub-message params
Do remember :
if several oneof fields are set in sequence, only the last
oneof
will be consider as final set value.
Reference :