protobuf 中的嵌套消息的使用

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

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

 

message PlayerPos{
	required  uint32  playerID = 1;
	required  float   posX = 2 ;
	required  float   posY = 3 ;
}

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

 

 

file  vector.proto

message  vector3D{
required float x = 1;
required float y = 2;
required float z = 3;
};

file  Player.proto

import "vector.proto";

message PlayerPos {
required uint32 playerID = 1;
required vector3D  pos = 2;
};

 

 

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

 

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;
  inline void set_playerid(::google::protobuf::uint32 value);

  // 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;
时间: 2024-08-24 21:52:45

protobuf 中的嵌套消息的使用的相关文章

protobuf 中的嵌套消息的使用 主要对set_allocated_和mutable_的使用

protobuf的简单的使用,不过还留下了一个问题,那就是之前主要介绍的都是对简单数据的赋值,简单数据直接采用set_xx()即可,但是如果不是简单变量而是自定义的复合类型变量,就没有简单的set函数调用了,下面看一个简单的例子. 在网络游戏中,游戏玩家之间的同步是一个最基本的功能,而同步是通过对坐标的广播进行的,因此我们假设一个简单的模型,当一个玩家的位置发生变化时,将玩家的新位置发给地图内所有玩家,根据这个情况写出以下proto文件.   [cpp] view plain copy   me

详解C++编程中的嵌套类的声明与其中的函数使用_C 语言

可以在一个类的范围内声明另一个类.这样的类称为"嵌套类". 嵌套类被视为在封闭类的范围内且可在该范围内使用.若要从嵌套类的即时封闭范围之外的某个范围引用该类,则必须使用完全限定名. 下面的示例演示如何声明嵌套类: // nested_class_declarations.cpp class BufferedIO { public: enum IOError { None, Access, General }; // Declare nested class BufferedInput.

监听器在游戏开发中的应用----消息回调

我一向是不太喜欢给一些东西强加上个名字.但为了随波逐流,我还是这样做了. 在我们的游戏开发中,通常会遇到两个模块之间的通信. 回调估计是最常用的方式了. 回调的设计思想很简单,就是两个对象相互注册,然后在需要的时候调用对方的函数. 如下: class B;   class A   {   public:       void RegisterCallback(B* pB)       {           m_pB = pB;       }       void ActiveA()     

深入探讨EJB中新的消息驱动组件

提要:我们可以使用MessageDrivenBean(消息驱动组件),在企业级的应用程序中进行异步的消息传送. 引言:Enterprise JavaBeans(EJB)1.1版本中定义了两种组件类型-session组件和entity组件.客户端对象可以同步调用EJB1.1的这两种组件的方法,然而,为了继承Message Oriented Middleware(MOM,面向对象的中间件)和Java Message Service(JMS,Java消息服务)的优点的需要,EJB框架中也相应的应当加入

关于ASP.NET编程中的嵌套If语句

本文将为大家简单介绍一下有关ASP.NET编程中的嵌套If语句的格式及用法,希望对大家有所帮助.下面就具体来看一下. 嵌套If语句 其格式如下: 以下是引用片段: If条件式1Then If条件式2Then 语句块1 Else 语句块1-2 EndIf 其他语句 Else 语句块2 EndIf 所谓的嵌套if语句,就是在If条件式中的语句块也是一组if条件式,其语句块又为一组if条件式,如此重复下去直到条件设置完毕. 一般而言,最复杂的条件式为嵌套条件式语句,以上所提到的所有条件式语句格式都可以

详解JavaScript中的客户端消息框架设计原理

  这篇文章主要介绍了详解JavaScript中的客户端消息框架设计原理,包括客户端和服务器端的通信等方面的内容,需要的朋友可以参考下 哇--是个危险的题目,对吗?我们对于什么是本质的理解当然会随着我们对要解决问题的理解而变化.因此我不会说谎--一年前我所理解的本质很不幸并不完整,因为我确信我将要写的已经快伴随我有6个月之久.所以,这篇文章是我在发现JavaScript中成功的运用客户端消息模式的一些关键要点时的一个掠影. 1.) 理解中介者与观察者的区别 大多数人在描述任何事件/消息机制的时候

在SQL Server的try...catch语句中获取错误消息代码的的语句

本文为大家详细介绍下如何在SQL Server的try...catch语句中获取错误消息的代码,具体示例如下,感兴趣的朋友可以参考下哈,希望对大家有所帮助   复制代码 代码如下: BEGIN TRY ... ... END TRY BEGIN CATCH DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; SELECT @ErrorMessage = ERROR_M

复制Windows中警告提示消息对话框内容的方法

  在使用Windows操作系统的时候,常常会由于各种操作而使系统弹出警告提示窗口,有的系统提示只是友情提示,有的则是系统错误,则需要我们去解决,通常的方法就是去网上搜索解决办法.那么在搜索之前,我们得先把错误的内容复制下来,以便于网友们根据错误提示内容来帮你解决具体的问题.然而系统弹出的警告提示窗口不可以用鼠标选择上面的文字,所以我们只能通过手动把警告提示窗口中的文字一个字一个字的键入到搜索引擎,实在是太麻烦了,所以今天就教大家复制Windows中警告提示消息对话框内容的方法. 这里假如我要关

请问java图形界面编程中怎样改变消息提示框中确定按钮的文本内容啊?

问题描述 请问java图形界面编程中怎样改变消息提示框中确定按钮的文本内容啊? 问题补充:恩恩,swing的!请问怎么改啊?xiaolv 写道 解决方案 JOptionPane.setDefaultLocale(Locale.CHINA);JOptionPane.showMessageDialog(null, "11", "22",JOptionPane.INFORMATION_MESSAGE);这个按钮自动集成多语言.只能通来Locale来改.想要OK就用Loca