找回密码
 立即注册
查看: 341|回复: 0

protobuf extend字段C++的使用方式

[复制链接]
发表于 2022-1-12 07:08 | 显示全部楼层 |阅读模式
前段时间参与一个多方开发的项目时,使用的某个proto文件中用到了extend字段的定义。在网上找了一圈使用方式,最终在只在Google的proto-buffer官网中看到,故此做个总结记录。
extend字段的作用

extend字段是用来对原有的message类型进行扩展的。在某些场景下,可能在定义了一个基础的消息类型之后,不同的使用方需要在这个基础的消息类型上添加自己的独有字段。又或者在后续的功能升级过程中需要对该消息类型增加新的字段。这个时候预先定义了extend字段的话,就可以直接对消息进行扩展,而不用修改原来的proto文件修改消息类型的定义了。
一个典型的使用场景如统一的数据管理平台,不同的使用方上传的数据使用的字段是不一样的,由平台方把所有可能使用到的字段写到同一份proto文件中显然是不可能的。如记录商品信息的数据需要的字段可能是商品名、商品价格、生产日期等,而记录职员信息的数据需要的字段是姓名、年龄、职位、工龄等。此时,平台接口定义的消息类型可以只包含诸如时间、使用者等统一字段,同时预留出足够的extend字段由使用者自行定义。
extend proto的定义

首先是平台定义自己需要用到的字段,并预留出可扩展的字段,下面的proto中的编号100~10000即为预留字段。
package xuetu;
message base {
    optional uint64 timestamp = 1;
    repeated string owner = 2;
    extensions 100 to 10000;
}
记录职员信息的数据proto就可以对上面的字段进行扩展并定义自己需要的字段,注意字段的id值只能是预留的extension范围。其中main.proto为原始定义的proto文件名。
package xuetu;
import "main.proto";
extend base {
    optional string name = 100;
    repeated string res= 101;
}
C++对extend字段的访问方式

与正常定义的message字段不同,extend增加的字段生成的cc和h文件中,没有针对每个字段都产生对应的“set_字段名”等函数用来设置、获取字段值。
对于extend字段,统一由HasExtension(), ExtensionSize(), ClearExtension(), GetExtension(), SetExtension(), MutableExtension(), AddExtension(), SetAllocatedExtension()和 ReleaseExtension()这几个函数进行操作。每个函数的第一个参数为需要操作的字段id名,后续参数与普通字段的操作函数类似。以下为一个根据上文的proto写到简单的示例程序,main.pb.h和person.pb.h分别为对应proto使用protoc生成的头文件。最后为程序输出的结果。
#include "main.pb.h"
#include "person.pb.h"
#include <iostream>

using namespace xuetu;
int main() {
    base test;

    //普通定义的optional、required字段,如timestamp字段
    //使用set_timestamp()设置
    //timestamp()获取
    std::cout << "========================timestamp==============" << std::endl;
    test.set_timestamp(1234);
    std::cout << "timestamp: " << test.timestamp() << std::endl;
    std::cout << "===============================================" << std::endl;
    std::cout << std::endl;

    //对于repeated字段owner
    //使用add_owner()增加值
    //使用owner_size()获取值的数量
    //使用owner(index)获取值
    std::cout << "========================owner==================" << std::endl;
    test.add_owner("zhangsan");
    test.add_owner("lisi");
    test.add_owner("wangwu");
    for (int i = 0; i < test.owner_size(); i++) {
        std::cout << "index:" << i << ", value:" << test.owner(i) << std::endl;
    }
    std::cout << "===============================================" << std::endl;
    std::cout << std::endl;

    //对于extend扩展的optional、required字段
    //使用SetExtension()设置值
    //使用GetExtension()获取值
    std::cout << "========================name===================" << std::endl;
    test.SetExtension(name, "xuetu");
    std::cout << "name:" << test.GetExtension(name) << std::endl;
    std::cout << "===============================================" << std::endl;
    std::cout << std::endl;

    //对于extend扩展的repeated字段
    //使用AddExtension()增加值
    //使用ExtensionSize()获取值的数量
    //使用GetExtension()获取值
    std::cout << "=======================res=====================" << std::endl;
    test.AddExtension(res, "res0");
    test.AddExtension(res, "res1");
    test.AddExtension(res, "res2");
    for (int i = 0; i < test.ExtensionSize(res); i++) {
       std::cout << "index:" << i << ", value:" << test.GetExtension(res, i) << std::endl;
    }
    std::cout << "===============================================" << std::endl;
    std::cout << std::endl;

    return 0;
}


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2025-5-14 15:39 , Processed in 0.175212 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表