Protobuf-net ist inkompatibel mit Google protobuf for C ++ (Nachrichtencodierung)

8

Wir hatten einige (viele) Klassen in .NET. Wir haben protobuf-net verwendet, um sie zu markieren und .proto-Wrapper für die C ++ - Codeseite über Google Original-Bibliothek .

Also habe ich eine Nachricht (C ++ DebugString () in einer EventBase-Klasse (in .NET EventCharacterMoved erbt EventBase , während ich in C ++ nur in die optionale Eigenschaft schreibe)):

%Vor%

(Aus einer solchen .proto-Datei)

%Vor%

In C ++ sende ich das und wir senden den gleichen Nachrichteninhalt von .NET.

Der C ++ - Code kann C ++ - codierte Nachrichten sowie .NET-codierte Nachrichten analysieren. Der .NET-Code kann die .NET-Nachricht nur analysieren.

Über den Draht werden 87 Bytes geflogen (dieselbe Größe wie in der .Net-Datei und C ++ - Datei ), der Inhalt ist jedoch unterschiedlich:

Wie Sie sehen können, ist es ähnlich, aber nicht gleich. Als Folge dieser Differenz kann CPP-Code .NET-C # -Nachrichten lesen, während .NET CPP-Nachrichten nicht lesen kann .

Im Code zur Deserialisierung erhalten wir:

  

Eine nicht behandelte Ausnahme vom Typ 'System.InvalidCastException' ist aufgetreten   in TestProto.exe

     

Zusätzliche Informationen: Objekt des Typs kann nicht umgewandelt werden   'TestProto.EventBase', um 'TestProto.EventCharacterMoved' einzugeben.

in Code wie:

%Vor%

Schauen wir uns an (wie in jpa in seinem Kommentar erwähnt) protoc --decode_raw option:

Dies kann damit zusammenhängen, dass mein CPP-Wrapper die neueste Google-Protobuf-Version verwendet, während protobuf-net wahrscheinlich ein älteres Kodierungsformat oder etwas ähnliches verwendet ...

Ich frage mich also, wie man .NET-Protobuf C ++ - Nachrichten lesen kann (damit das gleiche Zeug entschlüsselt werden kann)?

Oder zumindest, wie man originalen Google-Protobuf encodieren kann, genauso wie .NET-Protobuf?

Und für diejenigen, die wirklich interessiert sind und gerne in das Zip-Bundle mit vereinfachtem Beispiel (VS 2010-Lösungen) einsteigen möchten für C ++ und C # Code enthalten)

    
myWallJSON 24.12.2012, 10:46
quelle

2 Antworten

2

Bearbeiten; Dies sollte in r616 und darüber behoben werden.

Ich hatte endlich die Chance, das zu betrachten (Entschuldigung für Verspätung, aber soziale saisonbedingte Feiertagsforderungen). Ich verstehe, was jetzt passiert.

Grundsätzlich sind die Daten theoretisch identisch; Worauf es eigentlich ankommt, ist die Feldordnung. Technisch gesehen werden Felder normalerweise in aufsteigender Reihenfolge geschrieben, können aber in beliebiger Reihenfolge erwartet werden. In Bezug auf Protobuf-Net; Für Typen, die keine Vererbung beinhalten, funktioniert es unabhängig von der Reihenfolge. Die Protobuf-Spezifikation definiert keine Vererbung, daher fügt protobuf-net Unterstützung (aufgrund der konstanten Nachfrage) zusätzlich zu der Spezifikation hinzu. Als ein Implementierungsmerkmal schreibt es die Unterklasseninformation zuerst (d. H. Feld 15, der Untertyp, wird vor Feld 10 geschrieben). Zur Zeit der Deserialisierung erwartet die Information des Untertyps zuerst. Dies hat selten jemanden beeinflusst, da protobuf-net die einzige Implementierung ist, die eine Vererbung wie diese verwendet, die Verwendung der Vererbungsfunktion wird meistens nur mit der Verwendung von protobuf-net zu protobuf-net gesehen.

In Ihrem Fall verwenden Sie .proto, um mit CPP zu interagieren. Das bedeutet, dass der CPP-Code in der Lage ist, Daten von protobuf-net zu konsumieren, aber möglicherweise eine type-Cast-Ausnahme hat (im Grunde beginnt er, den konkreten Typ zu dem Zeitpunkt zu konstruieren, zu dem er das erste Datenfeld erhält) / p>

Obwohl dies selten ein Problem ist, muss dies behoben werden. Ich kann versuchen, mir das heute oder morgen anzuschauen.

Optionen:

  • stellen Sie sicher, dass die Untertyp-Felder immer niedriger sind als alle Datenfelder
  • Wenn Sie wissen, dass der Subtyp erwartet wird, verwenden Sie die Merge-API und übergeben Sie ein vorhandenes neues Objekt des gewünschten Typs. Dadurch wird das vorhandene Objekt korrekt gefüllt
  • Warten Sie einen oder zwei Tage (hoffentlich!) Verwenden Sie Build r616 oder höher für eine ordnungsgemäße Reparatur
  • Vermeiden Sie Vererbung (und andere implementierungsspezifische Features) bei der Verwendung von Interop
    • Beachten Sie, dass Sie dieselben Daten ohne Vererbung über Kapselung modellieren können - und es wird glücklich funktionieren; Es ist vor allem die Schaffung des konkreten Typs, der hier zum Thema wird
  • gehe zu unangemessenen Längen (das heißt: ich halte dies nicht für eine tatsächliche Lösung), wenn ich die Daten von der CPP-Site herstelle, indem ich sie in zwei Teile schreibe:
    • Schreiben Sie zuerst EventBase mit nur die EventCharacterMoved -Daten und serialisieren Sie sie; Schreiben Sie nun in einem separaten Modell ein EventBase mit nur die TreeFloat -Daten und serialisieren Sie; Dies simuliert das Schreiben in der erforderlichen Reihenfolge (Protobuf-Streams sind anhängbar) - nicht hübsch
Marc Gravell 31.12.2012, 07:52
quelle
1

Das sieht den in Ссылка und Ссылка , die angeblich durch Ссылка

Ist die Version von .NET-Protobuf, die Sie verwenden, neu genug, um dieses Update zu integrieren?

    
rici 26.12.2012 22:29
quelle