protobuf的簡單的使用,不過還留下了一個問題,那就是之前主要介紹的都是對簡單數(shù)據(jù)的賦值,簡單數(shù)據(jù)直接采用set_xx()即可,但是如果不是簡單變量而是自定義的復合類型變量,就沒有簡單的set函數(shù)調(diào)用了,下面看一個簡單的例子。
在網(wǎng)絡(luò)游戲中,游戲玩家之間的同步是一個最基本的功能,而同步是通過對坐標的廣播進行的,因此我們假設(shè)一個簡單的模型,當一個玩家的位置發(fā)生變化時,將玩家的新位置發(fā)給地圖內(nèi)所有玩家,根據(jù)這個情況寫出以下proto文件。
[cpp]?view plain
?copy message?PlayerPos?? {????? ????required??uint32??playerID?=?1;??? ????required??float???posX?=?2?;?????? ????required??float???posY?=?3?;?? };?? ?? file??vector.protomessage??vector3D?? {?? ????required?float?x?=?1;?? ????required?float?y?=?2;?? ????required?float?z?=?3;?? };??
這樣就有一個問題,現(xiàn)在的游戲都是3D游戲,因此需要xyz來表示位置,還需要另一組xyz來表示朝向,如果用簡單變量的話就會顯的很亂,而且無論是位置還是朝向其實都是一組xyz,因此可以將xyz抽出來成為一個復合數(shù)據(jù)類型,單獨放在一個文件中。這樣就構(gòu)成以下文件。
[cpp]?view plain
?copy file??Player.protoimport?"vector.proto";?? message?PlayerPos??? {?? ????required?uint32?playerID?=?1;?? ????required?vector3D??pos?=?2;?? };??
編譯的時候先編譯vector文件,采用import時需要注意路徑,本例中兩文件在同一目錄下。
[cpp]?view plain
?copy protoc?--cpp_out=.??vector.proto??Player.proto??
proto對應(yīng)的文件已經(jīng)生成了,但是該怎么賦值呢,查API查了半天有點不知所以,干脆來看生成的類文件的源代碼吧
[cpp]?view plain
?copy ?? 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);???? ?? 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的操作變量的函數(shù),第一個playID很簡單,可以看到直接使用set_playerid ( ) 即可,但是對于嵌套的pos 發(fā)現(xiàn)沒有對應(yīng)的set_pos方法,不過發(fā)現(xiàn)了一個set_allocated_pos() 函數(shù),這個函數(shù)也是set開頭的,看看這個函數(shù)是干嘛的。
[cpp]?view plain
?copy inline?void?PlayerPos::set_allocated_pos(::vector3D*?pos)??? {???? ????delete?pos_;???? ????pos_?=?pos;???? ????if?(pos)??? ????{?????? ????????set_has_pos();???? ????}??? ????else?{????? ?????????clear_has_pos();???? ????}?? }??
看上去可以賦值,直接調(diào)用set_allocated_pos() 進行賦值看一看
[cpp]?view plain
?copy PlayerPos?player;?? vector3D??tmp;?? tmp.x?=?1;?? tmp.y?=?2;?? tmp.z?=?3;?? player.set_allocated_pos(&tmp)??
編譯沒問題,但是運行時出現(xiàn)錯誤,而且是很奇怪的錯誤,仔細了查看一下PlayerPos的源碼,發(fā)現(xiàn)一個問題
[cpp]?view plain
?copy ::vector3D*?pos_;??::google::protobuf::uint32?playerid_;??
上面是PlayerPos中變量的保存形式,發(fā)現(xiàn)pos是作為一個指針存儲的,如果按照之前的賦值 tmp 是一個局部變量,函數(shù)返回時局部變量自動銷毀,而pos_保存的仍然是已被銷毀的tmp的位置,因此會出錯,如果采用new的話就可以解決這個問題,即賦值方法如下:
[cpp]?view plain
?copy PlayerPos?player;vector3D??*tmp?=?new?Vector3D;?? tmp->x?=?1;?? tmp->y?=?2;?? tmp->z?=?3;?? player.set_allocated_pos(tmp)??
這樣即可,編譯運行都沒有問題。?
如此之外,還有一種賦值方法,就是調(diào)用mutable_pos()
[cpp]?view plain
?copy inline?::vector3D*?PlayerPos::mutable_pos()??? {???? ????set_has_pos();???? ????if?(pos_?==?NULL)??? ????????pos_?=?new?::vector3D;???? ????return?pos_;?? }??
mutable_pos () 中自己new出了一個vector3D 對象,而vector3D中又實現(xiàn)了賦值的重載,因此可以這樣解決:
[cpp]?view plain
?copy PlayerPos?player;?? vector3D??*tmp?=?player.mutable_pos();?? tmp->x?=?1;?? tmp->y?=?2;?? tmp->z?=?3;??
總結(jié)
以上是生活随笔為你收集整理的protobuf 中的嵌套消息的使用 主要对set_allocated_和mutable_的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。