2009-02-07 20 views
75

Tengo una pequeña jerarquía de objetos que necesito serializar y transmitir a través de una conexión de socket. Necesito serializar el objeto, luego deserializarlo según el tipo que sea. ¿Hay alguna manera fácil de hacer esto en C++ (como en Java)?¿Cómo serializas un objeto en C++?

¿Hay algún ejemplo de código en línea de serialización en C++ o tutoriales?

EDIT: Para que quede claro, estoy buscando métodos para convertir un objeto en una matriz de bytes, y luego volver a un objeto. Puedo manejar la transmisión de socket.

+0

Eche un vistazo a [STLPLUS] [1], lib con implementación de persistencia. [1]: http: //stlplus.sourceforge.net/ – lsalamon

+2

Consulte [google :: protobuf] (http://code.google.com/p/protobuf/), es una biblioteca muy sólida y rápida para la serialización binaria . Lo hemos usado con éxito con boost :: asio, etc. – Ketan

+2

Las respuestas proporcionadas en realidad no explican * cómo * serializar. Uno ofrece la biblioteca de serialización de refuerzo, el otro explica los errores en una implementación ingenua. Como esta es la pregunta [tag: C++ - faq], ¿alguien puede responderla? –

Respuesta

50

Hablando de la serialización, me viene a la mente el boost serialization API. En cuanto a la transmisión de datos serializados a través de la red, usaría conectores de Berkeley o el asio library.

Editar:
Si desea realizar una serie de sus objetos a una matriz de bytes, puede utilizar el serializador impulso de la siguiente manera (tomado del sitio tutorial):

#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) 
    {} 
}; 

serialización real es entonces bastante fácil:

#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 
    } 

Deserialización funciona de forma análoga.

También hay mecanismos que le permiten manejar la serialización de punteros (estructuras de datos complejos como tress, etc. no son un problema), clases derivadas y puede elegir entre serialización binaria y de texto. Además, todos los contenedores STL son compatibles con la caja.

+0

Ver también: http://www.boost.org/doc/libs/1_37_0/doc/html/boost_asio.html –

+0

Esta es una pregunta en C++, ¿cómo es que la clase gps_position está sobrecargando el operador <<. No hay ninguna función de amigo definida –

+0

, observe el "amigo clase boost :: serialization :: access". Esto proporciona acceso de las funciones de la biblioteca de serialización a los miembros de la clase, incluso si son privados. –

13

En algunos casos, cuando se trata de tipos simples, que puede hacer:

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

eso está bien como una prueba de concepto o de primer borrador, para que otros miembros de su equipo pueden seguir trabajando en otra partes.

Pero tarde o temprano, generalmente antes, esto te hará daño!

llegas a tener problemas con:

  • tablas de punteros virtuales serán dañados.
  • Los punteros (a datos/miembros/funciones) estarán dañados.
  • Diferencias en relleno/alineación en diferentes máquinas.
  • Big/Little-Endian byte que ordena problemas.
  • Variaciones en la implementación de flotante/doble.

(Plus lo que necesita saber lo que son desembalaje en el lado de recepción.)

Puede mejorar este mediante el desarrollo de sus propios métodos de clasificación/unmarshalling para cada clase. (Idealmente virtuales, para que puedan extenderse en subclases). Unas simples macros te permitirán escribir diferentes tipos básicos con bastante rapidez en un orden grande/pequeño-endian-neutral.

Pero ese tipo de trabajo gruñido es mucho mejor, y más fácil, se maneja a través de boost's serialization library.

+0

Eso era algo en lo que estaba pensando. Pero como quiero serializar a una transmisión de red, esto no funciona en absoluto. A lo sumo debido a la endianidad y diferentes plataformas. Pero no sabía que corrompe los punteros virtuales. Gracias =) – Atmocreations

Cuestiones relacionadas