• C++ Protobuf


    Protobuf

    protobuf (protocol buffer) 是谷歌内部的混合语言数据标准。通过将结构化的数据进行序列化(串行化),用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

    • 序列化: 将结构数据或者对象转换成能够用于存储和传输的格式。

    • 反序列化: 在其他的计算环境中,将序列化后的数据还原为数据结构和对象

    下载安装

    sudo apt install autoconf automake libtool curl make g++ unzip
    https://github.com/protocolbuffers/protobuf/releases/
    cd protobuf
    ./autogen.sh
    ./configure
    make
    make check
    sudo make install
    sudo ldconfig
    

    Proto3中的数据类型限定修饰符:

    repeated 表示一个数组类型
    

    protobuf中常用的数据类型:

    • bool, 布尔类型
    • double, 64位浮点数
    • float, 32位浮点数
    • int32, 32位整数
    • int64, 64位整数
    • uint64, 64位无符号整数
    • sint32, 32位整数,处理负数效率更高
    • sint64, 64位整数,处理负数效率更高
    • string, 只能处理ASCII字符
    • bytes, 用于处理多字节的语言字符
    • enum, 枚举类型

    默认值

    解析消息时,如果编码的消息不包含特定的单数元素,则已分析对象中的相应字段将设置为该字段的默认值。这些默认值是特定于类型的:

    • 对于字符串,默认值为空字符串。
    • 对于字节,默认值为空字节。
    • 对于布尔值,默认值为 false。
    • 对于数值类型,默认值为零。
    • 对于枚举,默认值是第一个定义的枚举值,该值必须为 0。
    • 对于消息字段,未设置该字段。它的确切值取决于语言。

    举个栗子

    syntax = "proto3";	//默认proto2,这里用proto3
    
    package pt; //C++ 类似 namespace
    
    enum EnMsgType{
      EnMsgTypeP = 0; //占位
      LOGIN_MSG = 1;  // 登录消息
      LOGIN_MSG_ACK = 2; // 登录响应消息
      LOGIN_OUT_MSG = 3; // 注销消息
      REG_MSG = 4; // 注册消息
      REG_MSG_ACK = 5; // 注册响应消息
      ONE_CHAT_MSG = 6; // 聊天消息
      ADD_FRIEND_MSG = 7; // 添加好友消息
      CREATE_GROUP_MSG = 8; // 创建群组
      ADD_GROUP_MSG = 9; // 加入群组
      GROUP_CHAT_MSG = 10; // 群聊天
    }
    
    message MsgType{
      EnMsgType msgtype = 1;
    }
    
    enum ErrCode {
      SUCCESS = 0; //正确
      FAILURE = 1; //失败
      ONLINE = 2;  //已在线
    };
    
    message FriendsInfo {
      int32 id = 1;
      string name = 2;
      string state = 3;
    }
    
    message UsersInfo{
      int32 id = 1;
      string name = 2;
      string state = 3;
      string role = 4;
    }
    
    message GroupsInfo{
      int32 id = 1;
      string groupname = 2;
      string groupdesc = 3;
      repeated UsersInfo users = 4;
    }
    
    message Login {
      MsgType msgid = 1;
      int32 id = 2;
      string pwd = 3;
    }
    
    message LoginRsp{
      MsgType msgid = 1;
      int32 id = 2;
      string name = 3;
      repeated string offlinemsg = 4;
      repeated FriendsInfo friends = 5;
      repeated GroupsInfo groups = 6;
      ErrCode errcode = 7;
      string errmsg = 8;
    }
    

    生成代码

     protoc test.proto --cpp_out=./
    
    #include 
    #include "test.pb.h"
    
    int main() {
        pt::Register reg;
        pt::MsgType* msg = reg.mutable_msgid();
        msg->set_msgtype(pt::EnMsgType::LOGIN_MSG);
    
        reg.set_name("cmf");
        reg.set_pwd("123456");
        std::string str;
        reg.SerializeToString(&str);	//序列化
        std::cout << str.c_str() << std::endl;
    
        pt::Register res;
        if (res.ParseFromString(str)) {	//反序列化
            std::cout << res.msgid().msgtype() << " " << res.name() << " " << res.pwd() << std::endl;
        }
    
        pt::LoginRsp loginRsp;
        pt::MsgType* m = loginRsp.mutable_msgid();
        m->set_msgtype(pt::EnMsgType::LOGIN_MSG_ACK);
    
        loginRsp.set_id(1);
        loginRsp.set_name("cmf");
        loginRsp.set_errcode(pt::ErrCode::SUCCESS);
        loginRsp.set_errmsg("test");
        loginRsp.add_offlinemsg("nihao");
    
        pt::FriendsInfo *info = loginRsp.add_friends();
        info->set_name("cc");
        info->set_id(2);
        info->set_state("no");
        std::string strr;
        loginRsp.SerializeToString(&strr);
        std::cout << strr << std::endl;
    
        for (int i = 0; i < loginRsp.friends_size(); ++i) {
            pt::FriendsInfo info = loginRsp.friends(i);
            std::cout << info.name() << " " << info.id() << " " << info.state() << std::endl;
        }
        return 0;
    }
    

    编译运行加 -lprotobuf

    转换接口

    #include 
    
    using google::protobuf::util::JsonStringToMessage;
    
    bool proto_to_json(const google::protobuf::Message& message, std::string& json) {
        google::protobuf::util::JsonPrintOptions options;
        options.add_whitespace = true;
        options.always_print_primitive_fields = true;
        options.preserve_proto_field_names = true;
        return MessageToJsonString(message, &json, options).ok();
    }
    
    bool json_to_proto(const std::string& json, google::protobuf::Message& message) {
        return JsonStringToMessage(json, &message).ok();
    }
    

    __EOF__

  • 本文作者: 放飞梦想
  • 本文链接: https://www.cnblogs.com/chengmf/p/16631673.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    【WGS84坐标系】经纬度高度转换为WGS84坐标系对应的坐标值
    HTML批量文件上传方案——图像预览方式
    【React学习】React高级特性
    基于SAE堆叠自编码器的单维时间序列预测研究(matlab代码实现)
    Python刷算法题常见内置函数、方法技巧【最全汇总】
    ORACLE的utl_raw函数在不同字符集的数据库中的用法
    H指数----题解报告
    基于Part Affinity Fields的姿态估计后处理笔记
    2023 Shandong Provincial Collegiate Programming Contest
    Git 笔记
  • 原文地址:https://www.cnblogs.com/chengmf/p/16631673.html