google的protobuf是一种轻便高效的结构化数据存储格式,在通信协议和数据存储等领域中使用比较多。protobuf对于结构中的每个成员,会提供set系列函数和get系列函数。

但是,对于使用来说,需要根据传入的参数考虑需要调用的函数名,在使用这个比较多的情况,还是会让人觉得有些麻烦。而且,对于有些使用,例如之后打算不再使用protobuf,改为直接将数据压入内存段(The raw in-memory data structures sent/saved in binary form),或者直接压入内存段的方式,改为使用protobuf,那么,如果两者都是通过传入函数的方式来进行数据设置,或者数据解析,那么改动内容会比较少,而且出错几率也会比较低。那么如何实现呢?

先给出proto文件:

syntax = "proto2";package student;message Student
{required string name = 1;required int32 id = 2;optional int32 age = 3;optional string phoneNumber = 4;
}

下面给出通过函数重载方式,来处理各种参数类型的方式:

#include <google\protobuf\message.h>namespace goo_proto = ::google::protobuf;template <typename Param>
struct ProtoFunc
{static constexpr void* SetValueFunc = nullptr;
};template <>
struct ProtoFunc<goo_proto::int32>
{static constexpr auto SetValueFunc = &(goo_proto::Reflection::SetInt32);
};template <>
struct ProtoFunc<goo_proto::int64>
{static constexpr auto SetValueFunc = &(goo_proto::Reflection::SetInt64);
};template <>
struct ProtoFunc<std::string>
{static constexpr auto SetValueFunc = &(goo_proto::Reflection::SetString);
};template <>
struct ProtoFunc<const char*>
{static constexpr auto SetValueFunc = &(goo_proto::Reflection::SetString);
};template <typename ValueType>
void SetFieldValue(goo_proto::Message* msg, const goo_proto::Reflection* reflection,const goo_proto::FieldDescriptor* field, ValueType&& value)
{(reflection->*(ProtoFunc<std::remove_cv_t<std::decay_t<ValueType>>>::SetValueFunc))(msg, field, std::forward<ValueType>(value));
}

通过上述的模板,就可以调用SetFieldValue来处理int32, int64, std::string和const char*了,这个是实现泛型函数的前期准备。

下面给出一次设置多个参数的方式:

template <typename ...Args>
void SetFieldAllValues(goo_proto::Message* msg, Args&&... args)
{auto descriptor = msg->GetDescriptor();auto reflection = msg->GetReflection();SetFieldImpl<0>(msg, descriptor, reflection, std::forward<Args>(args)...);
}template <size_t idx, typename T, typename ...Args>
void SetFieldImpl(goo_proto::Message* msg, const goo_proto::Descriptor* descriptor, const goo_proto::Reflection* reflection,T&& value, Args&&... args)
{auto field = descriptor->field(idx);SetFieldValue(msg, reflection, field, std::forward<T>(value));SetFieldImpl<idx + 1>(msg, descriptor, reflection, std::forward<Args>(args)...);
}template <size_t idx>
void SetFieldImpl(goo_proto::Message* msg, const goo_proto::Descriptor* descriptor, const goo_proto::Reflection* reflection)
{// empty
}

上面就是实现,设置所有proto结构体中元素的方式。多谢protobuf中提供了descriptor::field函数,通过这个函数,我才有办法比较简单的实现通过传入所有的参数(这里没有考虑设置repeat成员),来一次性设置好整个proto结构体对象。下面看一下使用上述函数的一个实例:

#include <iostream>
#include <string>
#include "studentinfo.h"
#include "studentinfo.pb.h"int main(int argc, char* argv[])
{student::Student s;SetFieldAllValues(&s, "Jack", 10, 20, "11122233345");std::cout << s.name() << std::endl;std::cout << s.id() << std::endl;std::cout << s.age() << std::endl;std::cout << s.phonenumber() << std::endl;return 0;
}

这里只是提供了设置的函数(Set函数),没有提供Get函数,不过根据类似的方式,实现Get函数应该不是很困难,这里就不给出代码了。

转载于:https://www.cnblogs.com/albizzia/p/9153252.html

使用反射处理protobuf数据结构相关推荐

  1. 遍历protobuf数据结构

    我在将汉语写入protobuf的时候,遇到一个问题,如果需要将汉语写入protobuf,在序列化的时候没有报错,但解析失败,后来发现,需要将汉语转换成utf8格式写入,之后序列化成功. 解析proto ...

  2. 金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(原理篇)

    为什么80%的码农都做不了架构师?>>>    本文作者:丁同舟,转载自"随手记技术团队"微信公众号. 1.前言 跟移动端IM中追求数据传输效率.网络流量消耗等需 ...

  3. IM通讯协议专题学习(八):金蝶随手记团队的Protobuf应用实践(原理篇)

    本文由金蝶随手记技术团队丁同舟分享. 1.引言 跟移动端IM中追求数据传输效率.网络流量消耗等需求一样,随手记客户端与服务端交互的过程中,对部分数据的传输大小和效率也有较高的要求,普通的数据格式如 J ...

  4. Mina、Netty、Twisted一起学(五):整合protobuf

    protobuf是谷歌的Protocol Buffers的简称,用于结构化数据和字节码之间互相转换(序列化.反序列化),一般应用于网络传输,可支持多种编程语言. protobuf怎样使用这里不再介绍, ...

  5. 数据压缩:protobuf 的使用

    本文概要: protobuf 是什么,与 json 区别 protobuf 使用方式 性能对比 资料补充 protobuf 是什么 先看官方定义 protocol buffers 是一种语言无关.平台 ...

  6. caffe源码导读(二)Blob数据结构介绍

    文章目录 前言 一.先看Blob的数据结构描述 二.Blob基本用法 前言 本篇<深度学习21天实战caffe>这本书的阅读笔记. 打开proto/caffe.proto中,刚开始就是介绍 ...

  7. 还在用JSON? Google Protocol Buffers 更快更小 (原理篇)

    欢迎关注微信公众号「随手记技术团队」,查看更多随手记团队的技术文章.转载请注明出处 本文作者:丁同舟 原文链接:mp.weixin.qq.com/s/cyOHe1LS-- 背景 随手记客户端与服务端交 ...

  8. 启动优化·基础论·浅析 Android 启动优化

    " [小木箱成长营]启动优化系列文章(排期中): 启动优化 · 工具论 · 启动优化常见的六种工具 启动优化 · 方法论 · 这样做启动优化时长降低 70% 启动优化 · 实战论 · 手把手 ...

  9. 以 27K 成功入职字节跳动,这份《 软件测试面试笔记》让我受益终身...

    朋友入职已经两周了,整体工作环境还是非常满意的!所以这次特意抽空给我写出了这份面试题,而我把它分享给小伙伴们,面试&入职的经验! 大概是在5月中的时候他告诉我投递了简历,7月的时候经过了3轮面 ...

最新文章

  1. Codeforces 300E(数学)
  2. 北风设计模式课程---2、工厂方法模式
  3. 十天冲刺---Day8
  4. python 进阶案例_【python3】while和for的进阶案例
  5. 移动硬盘备份linux系统盘,将Ubuntu Linux系统放到你的移动硬盘
  6. 【第4篇】Python爬虫实战-抓取B站弹幕视频
  7. 论文阅读:Deep Image Matting
  8. L1-023. 输出GPLT-PAT团体程序设计天梯赛GPLT
  9. Hbase API实现倒序查询
  10. 全国青少年软件编程等级考试介绍
  11. SEEDLAB2.0-Meltdown
  12. Conmi的正确答案——米家第一个ReactNative程序开发记录
  13. 广告投放的相关名词CPM/CPT/CPC/CPD/CPI/CPS
  14. java xml格式化_使用java将xml格式化
  15. 算法竞赛---day1(等差素数列)
  16. win10系统如何看服务器地址,win10查看电脑DNS服务器地址具体步骤
  17. chrome怎么运行Android程序,ARCVM:Chrome OS 中运行 Android 应用程序的新方式
  18. hdoj 1276 士兵队列训练问题 模拟队列
  19. 达内python 资源_Python学习资源整理,优质Python学习资源推荐
  20. 计算机毕业设计Java中医药院校科研会议系统(源码+系统+mysql数据库+Lw文档)

热门文章

  1. MATLAB作图方法与技巧(二)
  2. HTML5新增的一些特性
  3. 04JavaScript中函数也是对象
  4. 2.监控软件zabbix-客户端安装
  5. CKEditor4.4.5 插入高度代码及上传图片
  6. 杭电1018 Big Number
  7. 关于linux内核无法编译成模块的解决方法
  8. java 中的 super
  9. sjms-2 创建型模式
  10. excel如何把顺序倒过来_Excel 中的计算运算符和优先顺序级别