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 = ;
required int32 id = ;
optional int32 age = ;
optional string phoneNumber = ;
}

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

#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<>(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 + >(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", , , "");
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 ;
}

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

google的protobuf简单介绍的更多相关文章

  1. Google Protocol Buffer 简单介绍

    以下内容主要整理自官方文档. 为什么使用 Protocol Buffers .proto文件 Protocol Buffers 语法 编译.proto文件 Protocol Buffers API 枚 ...

  2. Protobuf的简单介绍、使用和分析

      Protobuf的简单介绍.使用和分析   一.protobuf是什么? protobuf(Google Protocol Buffers)是Google提供一个具有高效的协议数据交换格式工具库( ...

  3. iOS开发拓展篇-XMPP简单介绍

    iOS开发拓展篇-XMPP简单介绍 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双 ...

  4. WebSocket简单介绍

    Java后端WebSocket的Tomcat实现 一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSoc ...

  5. TensorFlow简单介绍和在centos上的安装

    ##tensorflow简单介绍: TensorFlow™ is an open source software library for numerical computation using dat ...

  6. SQLite数据库和JPA简单介绍

    SQLite数据库和JPA简单介绍 一.SQLite简单使用 SQLite是遵循ACID的关系数据库管理系统,它的处理速度很快,它的设计目标是嵌入式的,只需要几百K的内存就可以了. 1.下载SQLit ...

  7. Epplus 使用的简单介绍

    操作Excel的主要有以下类库: MyXls(http://sourceforge.net/projects/myxls/) Koogra(http://sourceforge.net/project ...

  8. iOS开发——网络编程OC篇&(一)XMPP简单介绍与准备

    XMPP简单介绍与准备 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈 ...

  9. com.google.common.eventbus.EventBus介绍

    以下内容直接翻译了EventBus的注释: com.google.common.eventbus.EventBus介绍: 首先这个类是线程安全的, 分发事件到监听器,并提供相应的方式让监听器注册它们自 ...

随机推荐

  1. c# 后台处理获取的JSON 数据

    原创: http://www.imooc.com/article/8913 自己的例子: web.config <appSettings> <add key="GmailU ...

  2. ceph crush的问题

    ceph crush的问题看一遍忘一遍,现将<ceph源码分析>一书中相关章节摘抄如下: 4.2.1 层级化的Cluster Map例4-1 Cluster Map定义层级化的Cluste ...

  3. Python3+pyshark捕获数据包并保存为文件

    一.直接使用wireshark捕获数据包并保存为文件 可以使用wireshark通过图形界面的操作来实现捕获数据包并保存为文件. wireshark默认捕获的数据包保存为临时文件,如果最后退出时不选择 ...

  4. 阶段01Java基础day16集合框架02

    16.01_集合框架(去除ArrayList中重复字符串元素方式1) A:案例演示 需求:ArrayList去除集合中字符串的重复值(字符串的内容相同) 思路:创建新集合方式 /** * A:案例演示 ...

  5. java基础(1)IntelliJ IDEA入门和数组操作 解决idea启动速度慢--配置JVM

    一. IntelliJ IDEA入门 1 快捷键和技巧 智能补全代码,比如只写首字母按回车: psvm+Enter :public stactic void main(String[] args) s ...

  6. mybatis(一、原理,一对多,多对一查询)

    MyBatis框架及原理分析 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 ...

  7. Arcmap连接数据库需管理员获取许可——创建ArcSDE连接文件

    一.在装有server的服务器上创建ArcSDE连接文件 1.打开ArcMap<<ArcToolBox<<数据管理工具<<工作空间<<创建ArcSDE连 ...

  8. maven pom.xml配置文件详解

    1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/ ...

  9. Flex布局-容器的属性

    本文部分内容参考阮一峰大神博客,原文地址:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html Flex布局即弹性布局,使用起来十分方便灵活 ...

  10. java-Set集合、HashSet集合、LinkedHashSet集合和TreeSet集合

    1.Set集合,无索引,不可以重复,无序(存取不一致) public class Demo { public static void main(String[] args) { //demo1(); ...