2009-02-07 4 views
75

Ich habe eine kleine Hierarchie von Objekten, die ich über eine Socket-Verbindung serialisieren und übertragen muss. Ich muss das Objekt sowohl serialisieren als auch deserialisieren, je nachdem, um welchen Typ es sich handelt. Gibt es einen einfachen Weg, dies in C++ zu tun (wie es in Java gibt)?Wie serialisiert man ein Objekt in C++?

Gibt es irgendwelche C++ - Serialisierungs-Online-Codebeispiele oder -Tutorials?

EDIT: Nur um klar zu sein, ich suche nach Methoden zum Konvertieren eines Objekts in ein Array von Bytes, dann zurück in ein Objekt. Ich kann mit der Steckdosenübertragung umgehen.

+0

Werfen Sie einen Blick auf [STLPLUS] [1], lib mit Persistenz-Implementierung. [1]: http: //stlplus.sourceforge.net/ – lsalamon

+2

Schauen Sie sich [google :: protobuf] (http://code.google.com/p/protobuf/) an, es ist eine sehr starke und schnelle Bibliothek für die binäre Serialisierung . Wir haben es erfolgreich mit boost :: asio etc. verwendet. – Ketan

+2

Die angegebenen Antworten erklären nicht wirklich * wie * serialisieren. Einer bietet die Boost-Serialisierungs-Bibliothek an, der andere erklärt Fehler in einer naiven Implementierung. Da dies die Frage [tag: C++ - faq] ist, kann jemand tatsächlich antworten? –

Antwort

50

Wenn ich über die Serialisierung spreche, kommt mir die boost serialization API in den Sinn. Wie für die Übertragung der serialisierten Daten über das Netz, würde ich entweder Berkeley-Steckdosen oder die asio library verwenden.

Edit:
Wenn Sie Ihre Objekte in ein Byte-Array serialisieren möchten, können Sie die Boost-Serializer auf folgende Weise (aus dem Tutorial-Website) verwenden können:

#include <boost/archive/binary_oarchive.hpp> 
#include <boost/archive/binary_iarchive.hpp> 
class gps_position 
{ 
private: 
    friend class boost::serialization::access; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     ar & degrees; 
     ar & minutes; 
     ar & seconds; 
    } 
    int degrees; 
    int minutes; 
    float seconds; 

public: 
    gps_position(){}; 
    gps_position(int d, int m, float s) : 
    degrees(d), minutes(m), seconds(s) 
    {} 
}; 

Tatsächliche Serialisierung dann ganz einfach:

#include <fstream> 
std::ofstream ofs("filename.dat", std::ios::binary); 

    // create class instance 
    const gps_position g(35, 59, 24.567f); 

    // save data to archive 
    { 
     boost::archive::binary_oarchive oa(ofs); 
     // write class instance to archive 
     oa << g; 
     // archive and stream closed when destructors are called 
    } 

Die Deserialisierung funktioniert in analoger Weise.

Es gibt auch Mechanismen, mit denen Sie Serialisierung von Zeigern (komplexe Datenstrukturen wie Tress usw. sind kein Problem), abgeleitete Klassen und Sie können zwischen Binär-und Text-Serialisierung wählen können. Außerdem werden alle STL-Container direkt aus der Box unterstützt.

+0

Siehe auch: http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio.html –

+0

Dies ist eine C++ Frage, wie kommt es, dass die gps_position Klasse den Operator << überlädt. Es ist keine Freund-Funktion definiert –

+0

Beachten Sie die "Friend-Klasse boost :: serialization :: access". Dies ermöglicht den Klassenmitgliedern den Zugriff auf die Serialisierungsbibliotheksfunktionen, selbst wenn sie privat sind. –

13

In einigen Fällen, wenn sie mit einfachen Typen tun haben, können Sie tun:

object o; 
socket.write(&o, sizeof(o)); 

das ok ist, als ein Proof-of-Concept-oder First-Entwurf, so dass die anderen Mitglieder Ihres Teams halten können auf anderen Arbeits Teile.

Aber früher oder später, in der Regel eher, wird dies Sie verletzen!

Sie laufen in Probleme mit:

  • Virtuelle Zeigertabellen beschädigt werden.
  • Zeiger (zu Daten/Mitglieder/Funktionen) werden beschädigt.
  • Unterschiede in der Polsterung/Ausrichtung auf verschiedenen Maschinen.
  • Big/Little-Endian Byte Reihenfolge Probleme.
  • Variationen in der Implementierung von float/double.

(plus müssen Sie wissen, was Sie in auf der Empfangsseite sind Auspacken.)

Sie auf diese verbessern können Ihre eigenen Rangier-/unmarshalling Methoden für jede Klasse durch die Entwicklung. (Idealerweise virtuell, so dass sie in Unterklassen erweitert werden können.) Mit ein paar einfachen Makros können Sie verschiedene Basistypen ziemlich schnell in einer großen/kleinen endian-neutralen Reihenfolge schreiben.

Aber diese Art von Grunt Arbeit ist viel besser und einfacher, über boost's serialization library behandelt.

+0

Das war etwas worüber ich nachgedacht habe. Aber wie ich in einem Netzwerkstream serialisieren möchte, funktioniert das überhaupt nicht. Höchstens wegen der Endianz und verschiedener Plattformen. Aber ich wusste nicht, dass es virtuelle Zeiger korrumpiert. Danke =) – Atmocreations