protobuf的简单的使用,不过还留下了一个问题,那就是之前主要介绍的都是对简单数据的赋值,简单数据直接采用set_xx()即可,但是如果不是简单变量而是自定义的复合类型变量,就没有简单的set函数调用了,下面看一个简单的例子。

在网络游戏中,游戏玩家之间的同步是一个最基本的功能,而同步是通过对坐标的广播进行的,因此我们假设一个简单的模型,当一个玩家的位置发生变化时,将玩家的新位置发给地图内所有玩家,根据这个情况写出以下proto文件。

[cpp] view plain copy
  1. message PlayerPos
  2. {
  3. required  uint32  playerID = 1;
  4. required  float   posX = 2 ;
  5. required  float   posY = 3 ;
  6. };
  7. file  vector.protomessage  vector3D
  8. {
  9. required float x = 1;
  10. required float y = 2;
  11. required float z = 3;
  12. };

这样就有一个问题,现在的游戏都是3D游戏,因此需要xyz来表示位置,还需要另一组xyz来表示朝向,如果用简单变量的话就会显的很乱,而且无论是位置还是朝向其实都是一组xyz,因此可以将xyz抽出来成为一个复合数据类型,单独放在一个文件中。这样就构成以下文件。

[cpp] view plain copy
  1. file  Player.protoimport "vector.proto";
  2. message PlayerPos
  3. {
  4. required uint32 playerID = 1;
  5. required vector3D  pos = 2;
  6. };

编译的时候先编译vector文件,采用import时需要注意路径,本例中两文件在同一目录下。

[cpp] view plain copy
  1. protoc --cpp_out=.  vector.proto  Player.proto

proto对应的文件已经生成了,但是该怎么赋值呢,查API查了半天有点不知所以,干脆来看生成的类文件的源代码吧

[cpp] view plain copy
  1. // required uint32 playerID = 1;
  2. inline bool has_playerid() const;
  3. inline void clear_playerid();
  4. static const int kPlayerIDFieldNumber = 1;
  5. inline ::google::protobuf::uint32 playerid() const;
  6. inline void set_playerid(::google::protobuf::uint32 value);
  7. // required .vector3D pos = 2;
  8. inline bool has_pos() const;
  9. inline void clear_pos();
  10. static const int kPosFieldNumber = 2;
  11. inline const ::vector3D& pos() const;
  12. inline ::vector3D* mutable_pos();
  13. inline ::vector3D* release_pos();
  14. inline void set_allocated_pos(::vector3D* pos);

上面列出了生成的部分源代码,主要是PlayerPos的操作变量的函数,第一个playID很简单,可以看到直接使用set_playerid ( ) 即可,但是对于嵌套的pos 发现没有对应的set_pos方法,不过发现了一个set_allocated_pos() 函数,这个函数也是set开头的,看看这个函数是干嘛的。

[cpp] view plain copy
  1. inline void PlayerPos::set_allocated_pos(::vector3D* pos)
  2. {
  3. delete pos_;
  4. pos_ = pos;
  5. if (pos)
  6. {
  7. set_has_pos();
  8. }
  9. else {
  10. clear_has_pos();
  11. }
  12. }

看上去可以赋值,直接调用set_allocated_pos() 进行赋值看一看

[cpp] view plain copy
  1. PlayerPos player;
  2. vector3D  tmp;
  3. tmp.x = 1;
  4. tmp.y = 2;
  5. tmp.z = 3;
  6. player.set_allocated_pos(&tmp)

编译没问题,但是运行时出现错误,而且是很奇怪的错误,仔细了查看一下PlayerPos的源码,发现一个问题

[cpp] view plain copy
  1. ::vector3D* pos_;  ::google::protobuf::uint32 playerid_;

上面是PlayerPos中变量的保存形式,发现pos是作为一个指针存储的,如果按照之前的赋值 tmp 是一个局部变量,函数返回时局部变量自动销毁,而pos_保存的仍然是已被销毁的tmp的位置,因此会出错,如果采用new的话就可以解决这个问题,即赋值方法如下:

[cpp] view plain copy
  1. PlayerPos player;vector3D  *tmp = new Vector3D;
  2. tmp->x = 1;
  3. tmp->y = 2;
  4. tmp->z = 3;
  5. player.set_allocated_pos(tmp)

这样即可,编译运行都没有问题。 
如此之外,还有一种赋值方法,就是调用mutable_pos()

[cpp] view plain copy
  1. inline ::vector3D* PlayerPos::mutable_pos()
  2. {
  3. set_has_pos();
  4. if (pos_ == NULL)
  5. pos_ = new ::vector3D;
  6. return pos_;
  7. }

mutable_pos () 中自己new出了一个vector3D 对象,而vector3D中又实现了赋值的重载,因此可以这样解决:

[cpp] view plain copy
  1. PlayerPos player;
  2. vector3D  *tmp = player.mutable_pos();
  3. tmp->x = 1;
  4. tmp->y = 2;
  5. tmp->z = 3;

protobuf 中的嵌套消息的使用 主要对set_allocated_和mutable_的使用相关推荐

  1. C++ protobuf中对不同消息内容进行赋值的方式(set_、set_allocated_、mutable_、add_的使用)

    本文中用到的消息结构: message PointLLHA {// 通用的坐标点(经度纬度朝向高度),所有跟坐标相关的能够用就统一用这个optional double longitude = 1;// ...

  2. layui选项卡嵌套选项卡_在ProtoPie中使用嵌套组件构建选项卡栏

    layui选项卡嵌套选项卡 One of the powerful features of ProtoPie is the ability to build fully portable and in ...

  3. 区分 Protobuf 中缺失值和默认值

    转载地址:区分 Protobuf 中缺失值和默认值 - 知乎 Protobuf 是目前非常主流的二进制序列化格式,GRPC 默认使用 Protobuf v3 格式,下面是 Protobuf 消息定义的 ...

  4. sql 触发器嵌套条件_SQL Server中的嵌套触发器

    sql 触发器嵌套条件 Nested Triggers in SQL Server are actions that automatically execute when a certain data ...

  5. oracle数据库插入多表,在Oracle数据库中插入嵌套表

    我是PL/SQL数据库的新学习者,这是一种给apex.oracle.com上的数据库应用指定序列的练习.然后我创建了表格,但是当填充与插入的代码如下所示,应用赋予错误,表你不介意,我需要你的帮助在Or ...

  6. 在KVM中部署嵌套版本的VMware ESXi 6.7

    在KVM中部署嵌套版本的VMware ESXi 6.7 如果您在Ubuntu服务器上运行KVM,则您已经拥有出色的Type 1虚拟化引擎.幸运的是,如果您需要测试特定于VMware的产品,则始终可以运 ...

  7. Android中RecyclerView嵌套RecyclerView或嵌套ListView

    Android中RecyclerView嵌套RecyclerView或嵌套ListView

  8. C#中的MessageBox消息对话框

    关键字:C# MessageBox 消息对话框 在程序中,我们经常使用消息对话框给用户一定的信息提示,如在操作过程中遇到错误或程序异常,经常会使用这种方式给用于以提示.在C#中,MessageBox消 ...

  9. Python 中异常嵌套

    Python 中异常嵌套 参考文章: (1)Python 中异常嵌套 (2)https://www.cnblogs.com/johnyang/p/10409153.html 备忘一下.

最新文章

  1. 地图处理(dfs算法)
  2. SPSS学习笔记之——两独立样本的非参数检验(Mann-Whitney U )
  3. 详解JavaScript之神奇的Object.defineProperty
  4. python笔记之function函数
  5. 手机通话记录统计分析
  6. js 正则表达式总结
  7. 阿里云CentOS7服务器搭建邮件服务器,端口:465
  8. junit 单元测试插入操作事务回滚
  9. 怎样提高文章原创度,被快速收录?
  10. linux aaa认证服务器,华为设备安全之AAA认证
  11. 修改才是写作的本质所在
  12. COG注释[Ubuntu 15.10系统]
  13. 阿里Java后端开发面经,面试官都替我感到绝望
  14. 【房屋租赁网管理系统】
  15. 江南爱窗帘十大品牌 窗帘发展状况怎么样
  16. Tengine全面支持寒武纪思元芯片平台,共同推进AI芯片加速之路
  17. Matlab绘制线条消除锯齿
  18. Oracle数据库:自然连接natural join,using语句,注意避免写交叉连接
  19. 运行elevation_mapping流程记录
  20. 8. Android MultiMedia框架完全解析 - prepareAsync的过程分析

热门文章

  1. 用渐变色画圆_详细步骤!用ps画个中秋圆月亮
  2. AE牛顿动力学插件:Motion Boutique Newton 3 Mac(支持ae2021)
  3. 40款精简活力fcpx标题字幕 mTitle Kinetic for Mac
  4. ios开发跳转safari_iOS 跳转网页的四种方法
  5. jquery 判断点击次数_jquery编程开发实现点击页面计算点击次数
  6. 平衡二叉树平衡因子怎么计算_数据结构PHP 平衡二叉树(AVL)的平衡原理
  7. 判断是否是数字类型php_PHP函数补完:判断变量是否为数字is_numeric()
  8. Python笔记-使用SSIM找两张图不同及使用Opencv显示
  9. Linux笔记-bash中解决if语句中command not found问题
  10. Java工作笔记-注解的进一步理解