簡體   English   中英

Protobuf-net與C ++的官方Google Protobuf不兼容(消息編碼)

[英]Protobuf-net is incompatible with official google Protobuf for C++ (message encoding)

.NET中有一些(很多)類。 我們使用protobuf-net對其進行了標記,並通過google原始庫為C ++代碼端生成了.proto包裝器。

因此,我收到一條消息(某些EventBase類上的C ++ DebugString()(在.NET中, EventCharacterMoved繼承了EventBase而在C ++中,我只是寫入可選屬性)):

UserId: -2792
EventCharacterMoved {
  Coordinates {
    Position {
      X: 196.41913
      Y: 130
      Z: 213
    }
    Rotation {
      X: 207
      Y: 130
      Z: 213
    }
  }
  OldCoordinates {
    Position {
      X: 196.41913
      Y: 130
      Z: 213
    }
    Rotation {
      X: 207
      Y: 130
      Z: 213
    }
  }
}

(來自.proto文件)

message Coordinates {
   optional TreeFloat Position = 1;
   optional TreeFloat Rotation = 2;
}
message EventBase {
   optional int32 UserId = 10 [default = 0];
   // the following represent sub-types; at most 1 should have a value
   optional EventCharacterMoved EventCharacterMoved = 15;
}
message EventCharacterMoved {
   optional Coordinates Coordinates = 100;
   optional Coordinates OldCoordinates = 101;
}
message TreeFloat {
   optional float X = 1 [default = 0];
   optional float Y = 2 [default = 0];
   optional float Z = 3 [default = 0];
}

在C ++中,我發送此消息,然后從.NET發送相同的消息內容。

C ++代碼可以解析C ++編碼的消息以及.NET編碼的消息。 .NET代碼只能解析.NET消息。

通過電線,我們獲得了87個字節的飛行空間( .Net文件C ++文件的大小相同),但內容有所不同:

在此處輸入圖片說明

如您所見,其相似之處並不相同。 由於這種差異, CPP代碼可以讀取.NET C#消息,而.NET無法讀取CPP消息

在反序列化代碼中,我們得到:

TestProto.exe中發生了'System.InvalidCastException'類型的未處理異常

附加信息:無法將類型為“ TestProto.EventBase”的對象轉換為類型為“ TestProto.EventCharacterMoved”。

在像這樣的代碼中:

using (var inputStream = File.Open(@"./cpp_in.bin", FileMode.Open, FileAccess.Read)) {
    var ecm = Serializer.Deserialize<EventCharacterMoved>(inputStream);
}

讓我們看一下(如jpa在他的評論中提到的) protoc --decode_raw選項:

在此處輸入圖片說明

這可能與以下事實有關:我的CPP包裝器使用了最新的Google protobuf版本,而protobuf-net可能使用了一些較舊的編碼格式或類似的格式...

因此,我想知道如何使.NET protobuf讀取C ++消息(使tham能夠解碼相同內容)?

或者至少如何使原始的Google protobuf編碼與.NET protobuf相同?

對於那些真正感興趣並希望通過簡化示例進入壓縮包的用戶(包括適用於C ++和C#代碼的VS 2010解決方案)

編輯; 該問題應在r616及更高版本中修復。


我終於有機會研究一下(為延遲而道歉,但社交季節性假期需求有所干預)。 我了解現在發生了什么。

基本上,數據在理論上是相同的; 這實際上歸結為現場排序。 從技術上講,字段通常按升序編寫,但可以按任何順序期望。 關於protobuf網; 對於不涉及繼承的類型,無論順序如何,它都可以正常工作。 protobuf規范沒有定義繼承,因此protobuf-net在規范的基礎上(由於不斷的需求) 增加了對該繼承的支持。 作為一種實施的功能時,它首先寫入(即字段15,子類型,則提前寫入字段10)的子類的信息。 當前,在反序列化期間,它也首先需要子類型信息。 這幾乎對任何人都沒有影響,因為既然protobuf-net是唯一這樣使用繼承的實現,那么繼承功能的使用通常僅在protobuf-net到protobuf-net的使用中才能看到。

就您而言,您正在使用.proto與CPP互操作; 這意味着CPP代碼將能夠使用protobuf-net數據,但是它可能會有類型轉換異常(反之亦然)(基本上,它在獲取第一個數據字段時便開始構造具體類型)。

盡管很少有問題,但這是需要解決的問題。 我可以嘗試今天晚些時候或明天看看。

選項:

  • 確保子類型字段始終低於任何數據字段
  • 如果您知道期望該子類型,請使用Merge API並傳入所需類型的現有新對象-然后,它將正確填充現有對象
  • 等待一兩天(希望如此!)使用內部版本r616或更高版本進行正確修復
  • 使用互操作時避免繼承(以及其他實現特定的功能)
    • 請注意,您可以通過封裝對相同的數據進行建模而無需繼承-它會很愉快地工作; 特別是具體類型的創建是這里的問題
  • 在CPP網站上構造數據時,請分兩段來寫一些不合理的長度(意思是:我認為這不是實際的解決方案):
    • EventBase 編寫帶有EventCharacterMoved數據的EventBase ,然后進行序列化; 現在在一個單獨的模型中, 使用TreeFloat數據編寫一個EventBase並進行序列化; 這將模擬按要求的順序編寫它們(protobuf流是可附加的)-不太漂亮

這看起來與http://code.google.com/p/protobuf-net/issues/detail?id=299http://code.google.com/p/protobuf-net/issues中指出的問題非常相似/ detail?id = 331 ,據稱由http://code.google.com/p/protobuf-net/source/detail?r=595修復。

您使用的.NET protobuf版本是否足夠新,可以合並該修復程序?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM