protobuf 巢狀訊息的使用
阿新 • • 發佈:2019-01-29
protobuf的簡單的使用,不過還留下了一個問題,那就是之前主要介紹的都是對簡單資料的賦值,簡單資料直接採用set_xx()即可,但是如果不是簡單變數而是自定義的複合型別變數,就沒有簡單的set函式呼叫了,下面看一個簡單的例子。
在網路遊戲中,遊戲玩家之間的同步是一個最基本的功能,而同步是通過對座標的廣播進行的,因此我們假設一個簡單的模型,當一個玩家的位置發生變化時,將玩家的新位置發給地圖內所有玩家,根據這個情況寫出以下proto檔案。
- message PlayerPos
- {
- required uint32 playerID = 1;
- required float posX = 2 ;
- required float posY = 3 ;
- };
- file vector.protomessage vector3D
- {
-
required float
- required float y = 2;
- required float z = 3;
- };
- file Player.protoimport "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;
- inlinebool has_playerid() const;
-
inlinevoid clear_playerid();
- staticconstint kPlayerIDFieldNumber = 1;
- inline ::google::protobuf::uint32 playerid() const;
- inlinevoid set_playerid(::google::protobuf::uint32 value);
- // required .vector3D pos = 2;
- inlinebool has_pos() const;
- inlinevoid clear_pos();
- staticconstint kPosFieldNumber = 2;
- inlineconst ::vector3D& pos() const;
- inline ::vector3D* mutable_pos();
- inline ::vector3D* release_pos();
- inlinevoid set_allocated_pos(::vector3D* pos);
上面列出了生成的部分原始碼,主要是PlayerPos的操作變數的函式,第一個playID很簡單,可以看到直接使用set_playerid ( ) 即可,但是對於巢狀的pos 發現沒有對應的set_pos方法,不過發現了一個set_allocated_pos() 函式,這個函式也是set開頭的,看看這個函式是幹嘛的。
- inlinevoid PlayerPos::set_allocated_pos(::vector3D* pos)
- {
- delete pos_;
- pos_ = pos;
- if (pos)
- {
- set_has_pos();
- }
- else {
- clear_has_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 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_;
- }
- PlayerPos player;
- vector3D *tmp = player.mutable_pos();
- tmp->x = 1;
- tmp->y = 2;
- tmp->z = 3;