如何创建使用oneof定义的Protobuf消息并实现序列化与解析
Protobuf C++ oneof字段使用方法
Protobuf针对oneof内定义的消息类型字段,不会生成普通的set_xxx()接口,而是提供了专属的操作方法,具体操作逻辑如下:
发送端构造消息
对于oneof内的三类消息,构造方式如下:
- 构造
start_now/stop_now消息:直接调用对应mutable_xxx()方法即可,因为SimpleMessage是空消息,调用方法后就完成了赋值,oneof对应的PayloadCase会自动更新 - 构造
heart_beat消息:调用mutable_heart_beat()拿到Jacket类型的指针,再设置其中的value字段即可
示例代码:
#include "生成的proto头文件名称.pb.h" #include <string> #include <iostream> int main() { // 构造start_now消息 jomba::Message start_msg; start_msg.mutable_start_now(); // 序列化 std::string start_serialized; start_msg.SerializeToString(&start_serialized); // 构造stop_now消息 jomba::Message stop_msg; stop_msg.mutable_stop_now(); std::string stop_serialized; stop_msg.SerializeToString(&stop_serialized); // 构造heart_beat消息 jomba::Message hb_msg; auto* hb_payload = hb_msg.mutable_heart_beat(); hb_payload->set_value(2048); std::string hb_serialized; hb_msg.SerializeToString(&hb_serialized);
接收端解析消息
解析时先调用ParseFromString()完成反序列化,再通过payload_case()方法判断当前oneof设置的是哪类消息,再读取对应内容即可:
// 接收到序列化后的数据后执行解析 jomba::Message recv_msg; if (recv_msg.ParseFromString(hb_serialized)) { switch (recv_msg.payload_case()) { case jomba::Message::kStartNow: std::cout << "接收到启动指令" << std::endl; break; case jomba::Message::kStopNow: std::cout << "接收到停止指令" << std::endl; break; case jomba::Message::kHeartBeat: std::cout << "接收到心跳消息,数值为:" << recv_msg.heart_beat().value() << std::endl; break; case jomba::Message::PAYLOAD_NOT_SET: std::cout << "消息无有效载荷" << std::endl; break; } } return 0; }
注意事项
- 当你对oneof的另一个字段调用
mutable_xxx()方法时,之前设置的oneof字段会被自动释放,符合oneof同一时间仅一个字段有效的规则 - 不需要手动修改
PayloadCase枚举的值,调用对应mutable方法时会自动更新该枚举值 - 除了用
payload_case()判断字段类型,也可以直接调用has_start_now()、has_stop_now()、has_heart_beat()方法判断对应字段是否被设置
内容的提问来源于stack exchange,提问作者Tellrell White
相关产品推荐
相关产品推荐

