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
oneofwill be consider as final set value.
Reference :