protobuf 中的嵌套消息的使用
来源:互联网 发布:淘宝直通车 如何出价 编辑:程序博客网 时间:2024/05/29 02:55
之前已经介绍了protobuf的简单的使用,不过还留下了一个问题,那就是之前主要介绍的都是对简单数据的赋值,简单数据直接采用set_xx()即可,但是如果不是简单变量而是自定义的复合类型变量,就没有简单的set函数调用了,下面看一个简单的例子。
在网络游戏中,游戏玩家之间的同步是一个最基本的功能,而同步是通过对坐标的广播进行的,因此我们假设一个简单的模型,当一个玩家的位置发生变化时,将玩家的新位置发给地图内所有玩家,根据这个情况写出以下proto文件。
message PlayerPos{required uint32 playerID = 1;required float posX = 2 ;required float posY = 3 ;}这样就有一个问题,现在的游戏都是3D游戏,因此需要xyz来表示位置,还需要另一组xyz来表示朝向,如果用简单变量的话就会显的很乱,而且无论是位置还是朝向其实都是一组xyz,因此可以将xyz抽出来成为一个复合数据类型,单独放在一个文件中。这样就构成以下文件。
<span style="color: rgb(255, 0, 0);">file vector.proto</span>message vector3D{required float x = 1;required float y = 2;required float z = 3;};<span style="color: rgb(255, 0, 0);">file Player.proto</span>import "vector.proto";message PlayerPos {required uint32 playerID = 1;required vector3D pos = 2;};
protoc --cpp_out=. vector.proto Player.proto
proto对应的文件已经生成了,但是该怎么赋值呢,查API查了半天有点不知所以,干脆来看生成的类文件的源代码吧
// required uint32 playerID = 1; inline bool has_playerid() const; inline void clear_playerid(); static const int kPlayerIDFieldNumber = 1; inline ::google::protobuf::uint32 playerid() const; <span style="color: rgb(255, 0, 0);">inline void set_playerid(::google::protobuf::uint32 value);</span> // required .vector3D pos = 2; inline bool has_pos() const; inline void clear_pos(); static const int kPosFieldNumber = 2; inline const ::vector3D& pos() const; inline ::vector3D* mutable_pos(); inline ::vector3D* release_pos(); inline void set_allocated_pos(::vector3D* pos);
上面列出了生成的部分源代码,主要是PlayerPos的操作变量的函数,第一个playID很简单,可以看到直接使用set_playerid ( ) 即可,但是对于嵌套的pos 发现没有对应的set_pos方法,不过发现了一个set_allocated_pos() 函数,这个函数也是set开头的,看看这个函数是干嘛的。
inline void PlayerPos::set_allocated_pos(::vector3D* pos) { delete pos_; pos_ = pos; if (pos) { set_has_pos(); } else { clear_has_pos(); }}
看上去可以赋值,直接调用set_allocated_pos() 进行赋值看一看
PlayerPos player;vector3D tmp;tmp.x = 1;tmp.y = 2;tmp.z = 3;player.set_allocated_pos(&tmp)
编译没问题,但是运行时出现错误,而且是很奇怪的错误,仔细了查看一下PlayerPos的源码,发现一个问题
::vector3D* pos_; ::google::protobuf::uint32 playerid_;
上面是PlayerPos中变量的保存形式,发现pos是作为一个指针存储的,如果按照之前的赋值 tmp 是一个局部变量,函数返回时局部变量自动销毁,而pos_保存的仍然是已被销毁的tmp的位置,因此会出错,如果采用new的话就可以解决这个问题,即赋值方法如下
PlayerPos player;vector3D *tmp = new Vector3D;tmp->x = 1;tmp->y = 2;tmp->z = 3;player.set_allocated_pos(tmp)
这样即可,编译运行都没有问题。
如此之外,还有一种赋值方法,就是调用mutable_pos()
inline ::vector3D* PlayerPos::mutable_pos() { set_has_pos(); if (pos_ == NULL) pos_ = new ::vector3D; return pos_;}
mutable_pos () 中自己new出了一个vector3D 对象,而vector3D中又实现了赋值的重载,因此可以这样解决
PlayerPos player;vector3D *tmp = player.mutable_pos();tmp->x = 1;tmp->y = 2;tmp->z = 3;
0 0
- protobuf 中的嵌套消息的使用
- protobuf 中的嵌套消息的使用
- protobuf 嵌套消息的使用
- protobuf 中的嵌套消息的使用 主要对set_allocated_和mutable_的使用
- protobuf 中的嵌套消息的使用 主要对set_allocated_和mutable_的使用
- 使用protobuf定义消息
- 使用protobuf定义消息
- 使用protobuf和socket实现服务器间消息的传递
- protobuf java中的使用
- protobuf的nested message嵌套消息。有时会出现序列话再反序列化后,嵌套消息的指却没有了
- protobuf消息的自动派发
- Protobuf在Python中的使用
- protobuf 在lua中的使用
- Protobuf在Java中的使用
- Protobuf在Python中的使用
- 使用自己的Python函数处理Protobuf中的字符串编码
- 【Google Protobuf】protobuf的使用(二)
- Google Protobuf的使用
- Apache的虚拟目录和虚拟主机设置
- IOS数据存储之---Core Data
- google_protobuf数据类型
- Appium 简明教程
- IOS UITableView 局部刷新
- protobuf 中的嵌套消息的使用
- ubuntu下实现多个pdf文件合并
- 黑马程序员—C语言输入与输出
- protobuf文件嵌套结构实例
- Android SDK 在线更新镜像服务器资源
- 替换字符串,裁掉字符串两端的空格---轻开平台(原WebEasy)字符串计算6
- poj 3693 Maximum repetition substring(08合肥 RMQ+后缀数组)
- Java 序列化与反序列化
- 习题10-18 一个研究课题 UVa10837