使用反射处理protobuf数据结构
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数据结构相关推荐
- 遍历protobuf数据结构
我在将汉语写入protobuf的时候,遇到一个问题,如果需要将汉语写入protobuf,在序列化的时候没有报错,但解析失败,后来发现,需要将汉语转换成utf8格式写入,之后序列化成功. 解析proto ...
- 金蝶随手记团队分享:还在用JSON? Protobuf让数据传输更省更快(原理篇)
为什么80%的码农都做不了架构师?>>> 本文作者:丁同舟,转载自"随手记技术团队"微信公众号. 1.前言 跟移动端IM中追求数据传输效率.网络流量消耗等需 ...
- IM通讯协议专题学习(八):金蝶随手记团队的Protobuf应用实践(原理篇)
本文由金蝶随手记技术团队丁同舟分享. 1.引言 跟移动端IM中追求数据传输效率.网络流量消耗等需求一样,随手记客户端与服务端交互的过程中,对部分数据的传输大小和效率也有较高的要求,普通的数据格式如 J ...
- Mina、Netty、Twisted一起学(五):整合protobuf
protobuf是谷歌的Protocol Buffers的简称,用于结构化数据和字节码之间互相转换(序列化.反序列化),一般应用于网络传输,可支持多种编程语言. protobuf怎样使用这里不再介绍, ...
- 数据压缩:protobuf 的使用
本文概要: protobuf 是什么,与 json 区别 protobuf 使用方式 性能对比 资料补充 protobuf 是什么 先看官方定义 protocol buffers 是一种语言无关.平台 ...
- caffe源码导读(二)Blob数据结构介绍
文章目录 前言 一.先看Blob的数据结构描述 二.Blob基本用法 前言 本篇<深度学习21天实战caffe>这本书的阅读笔记. 打开proto/caffe.proto中,刚开始就是介绍 ...
- 还在用JSON? Google Protocol Buffers 更快更小 (原理篇)
欢迎关注微信公众号「随手记技术团队」,查看更多随手记团队的技术文章.转载请注明出处 本文作者:丁同舟 原文链接:mp.weixin.qq.com/s/cyOHe1LS-- 背景 随手记客户端与服务端交 ...
- 启动优化·基础论·浅析 Android 启动优化
" [小木箱成长营]启动优化系列文章(排期中): 启动优化 · 工具论 · 启动优化常见的六种工具 启动优化 · 方法论 · 这样做启动优化时长降低 70% 启动优化 · 实战论 · 手把手 ...
- 以 27K 成功入职字节跳动,这份《 软件测试面试笔记》让我受益终身...
朋友入职已经两周了,整体工作环境还是非常满意的!所以这次特意抽空给我写出了这份面试题,而我把它分享给小伙伴们,面试&入职的经验! 大概是在5月中的时候他告诉我投递了简历,7月的时候经过了3轮面 ...
最新文章
- Codeforces 300E(数学)
- 北风设计模式课程---2、工厂方法模式
- 十天冲刺---Day8
- python 进阶案例_【python3】while和for的进阶案例
- 移动硬盘备份linux系统盘,将Ubuntu Linux系统放到你的移动硬盘
- 【第4篇】Python爬虫实战-抓取B站弹幕视频
- 论文阅读:Deep Image Matting
- L1-023. 输出GPLT-PAT团体程序设计天梯赛GPLT
- Hbase API实现倒序查询
- 全国青少年软件编程等级考试介绍
- SEEDLAB2.0-Meltdown
- Conmi的正确答案——米家第一个ReactNative程序开发记录
- 广告投放的相关名词CPM/CPT/CPC/CPD/CPI/CPS
- java xml格式化_使用java将xml格式化
- 算法竞赛---day1(等差素数列)
- win10系统如何看服务器地址,win10查看电脑DNS服务器地址具体步骤
- chrome怎么运行Android程序,ARCVM:Chrome OS 中运行 Android 应用程序的新方式
- hdoj 1276 士兵队列训练问题 模拟队列
- 达内python 资源_Python学习资源整理,优质Python学习资源推荐
- 计算机毕业设计Java中医药院校科研会议系统(源码+系统+mysql数据库+Lw文档)