<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

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

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    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.   
    8. file  vector.protomessage  vector3D  
    9. {  
    10.     required float x = 1;  
    11.     required float y = 2;  
    12.     required float z = 3;  
    13. };  

    這樣就有一個問題,現在的游戲都是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;  
    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全