Pregunta

tengo una pequeña jerarquía de objetos que necesito para serializar y transmitir a través de una conexión de socket. Necesito tanto serializar el objeto, a continuación, deserializar que sobre la base de qué tipo es. ¿Hay una manera fácil de hacer esto en C ++ (como lo hay en Java)?

¿Hay ++ ejemplos de código de serialización línea C o tutoriales?

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

¿Fue útil?

Solución

Hablando de serialización, la impulsar la serialización API me viene a la mente. En cuanto a la transmisión de los datos serializados en la red, yo bien utilizar sockets Berkeley o el asio biblioteca .

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 una manera análoga.

También hay mecanismos que permiten gestionar la serialización de punteros (estructuras de datos complejas, como árboles, etc no son un problema), las clases derivadas y se puede elegir entre serialización binaria y texto. Además de todos los contenedores STL son compatibles fuera de la caja.

Otros consejos

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 otras partes.

Pero tarde o temprano, generalmente más pronto , esto hará que le duele!

tenga problemas con:

  • se corromperá tablas de punteros virtuales.
  • Punteros (a datos / miembros / funciones) será dañado.
  • Las diferencias en el acolchado / alineación en diferentes máquinas.
  • temas
  • grande / pequeño-endian orden de bytes.
  • Las variaciones en la implementación de flotador / doble.

(Plus 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. (Lo ideal es virtual, por lo que se puede extender en las subclases.) Unos simples macros le permitirá a escribir a cabo diferentes tipos básicos con bastante rapidez en un orden grande / pequeño-endian-neutro.

Sin embargo, ese tipo de trabajo pesado es mucho mejor y más fácilmente, se maneja a través de biblioteca de serialización de impulso .

La serialización significa convertir el objeto en datos binarios. Mientras deserialización significa recrear un objeto de los datos.

Cuando seria usted está empujando bytes en un vector de uint8_t. Cuando revertir la seriación que está leyendo bytes desde un vector de uint8_t.

Es cierto que hay patrones que se puede aplicar en la serialización de cosas.

Cada clase serializable debe tener un serialize(std::vector<uint8_t> &binaryData) o función signatura similar que va a escribir su representación binaria en el vector proporcionado. A continuación, esta función puede pasar este vector a fin de cuentas es la serialización de las funciones de miembros para que puedan escribir sus cosas en él también.

Desde la representación de datos puede ser diferente en diferentes arquitecturas. Es necesario encontrar un esquema de cómo representar los datos.

Vamos a empezar desde lo básico:

números de serie a datos enteros

Sólo tiene que escribir los bytes en poco orden endian. O utilizar la representación varint si el tamaño importa.

La serialización en poco orden endian:

data.push_back(integer32 & 0xFF);
data.push_back((integer32 >> 8) & 0xFF);
data.push_back((integer32 >> 16) & 0xFF);
data.push_back((integer32 >> 24) & 0xFF);

Deserialización desde little endian orden:

integer32 = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);

La serialización de datos de punto flotante

Por lo que sé que el IEEE 754 tiene un monopolio aquí. No sé de cualquier arquitectura de la corriente principal que usar algo más de flotadores. La única cosa que puede ser diferente es el orden de bytes. Algunas arquitecturas usan poco endian, otros utilizan la orden grande byte más significativo. Esto significa que hay que tener cuidado, que a fin de que en voz alta los bytes en el extremo receptor. Otra diferencia puede ser el manejo de los valores NAN denormal y el infinito y más. Pero siempre y cuando se evite estos valores debe estar bien.

La serialización:

uint8_t mem[8];
memcpy(mem, doubleValue, 8);
data.push_back(mem[0]);
data.push_back(mem[1]);
...

Deserialización lo está haciendo hacia atrás. Cuidado con el orden de bytes de la arquitectura!

cadenas Serialización

Lo primero que necesita ponerse de acuerdo sobre una codificación. UTF-8 es común. A continuación, guárdelo como una forma de longitud prefijada:. Primera almacenar la longitud de la cadena mediante un método que he mencionado anteriormente, a continuación, escribir la cadena de bytes por byte

La serialización de matrices.

Son los mismos que una cuerdas. Usted primera serializar un entero que representa el tamaño de la matriz a continuación serializar cada objeto en ella.

objetos enteros Serialización

Como ya he dicho antes que deberían tener un método serialize que agregar contenido a un vector. Para serializar un objeto, éste debe tener un constructor que toma flujo de bytes. Puede ser una istream pero en el caso más sencillo puede ser simplemente un puntero uint8_t referencia. El constructor lee los bytes que quiere de la corriente y establece los campos en el objeto. Si el sistema está bien diseñado y serializar los campos en el orden de campo de objeto, puede simplemente pasar la corriente a los constructores del campo en una lista de inicialización y hacer que deserializado en el orden correcto.

Serialización de gráficos de objetos

Lo primero que necesita para asegurarse de si estos objetos son realmente algo desea realizar una serie. No es necesario para serializar ellos si las instancias de estos objetos presentes en el destino.

Ahora usted descubrió que necesita para serializar ese objeto apuntado por el puntero. El problema de los punteros que son válidos sólo el programa en el que los utiliza. No se puede serializar puntero, debe dejar de usarlos en los objetos. En su lugar crear grupos de objetos. Esta agrupación de objetos es básicamente una matriz dinámica que contiene "cajas". Estas cajas tienen un recuento de referencia. contador de referencia distinto de cero indica un objeto vivo, cero indica una ranura vacía. A continuación, se crea puntero inteligente similar a la shared_ptr que no almacena el puntero al objeto, pero el índice de la matriz. También es necesario ponerse de acuerdo sobre un índice que indica el puntero nulo, por ejemplo. -1.

Básicamente lo que hicimos aquí se sustituye con los punteros índices de matriz. Ahora, cuando la serialización puede serializar este índice de la matriz como de costumbre. Usted no necesita preocuparse de dónde viene el objecT será en la memoria del sistema de destino. Sólo asegúrese de que tengan la misma agrupación de objetos también.

Así que necesitamos para serializar los objetos piscinas. Pero, ¿cuáles? Bien al serializar un objeto gráfico no está serializando sólo un objeto, que está serializando todo un sistema. Esto significa que la serialización del sistema no debe partir de partes del sistema. Esos objetos no deben preocuparse por el resto del sistema, sólo necesitan para serializar los índices de matriz y eso es todo. Usted debe tener una rutina serializador sistema que orquesta la serialización del sistema y guía a través de las piscinas de objetos relevantes y serializar todos ellos.

En el extremo receptor todas las matrices una los objetos dentro están deserializado, recreando el gráfico objeto deseado.

Serialización de los punteros de función

No almacenar punteros en el objeto. Tener una matriz estática que contiene los punteros a estas funciones y almacenar el índice en el objeto.

Dado que ambos programas han compilado en esta tabla themshelves, utilizando simplemente el índice debería funcionar.

Serialización tipos polimórficos

Desde que dije se debe evitar punteros en tipos serializables y usted debe utilizar los índices de matriz en su lugar, el polimorfismo simplemente no puede funcionar, ya que requiere punteros.

Es necesario trabajar con esto alrededor de etiquetas de tipo y los sindicatos.

versiones

Además de todo lo anterior. Es posible que desee diferentes versiones del software de interoperar.

En este caso, cada objeto debe escribir un número de versión en el comienzo de su serialización para indicar la versión.

Al cargar el objeto en el otro lado, los nuevos objetos tal vez capaz de manejar las representaciones más antiguas pero los mayores no pueden manejar la más reciente por lo que debe lanzar una excepción al respecto.

Cada vez que cambia un algo, se debe volcar el número de versión.


Así que para terminar con esto, la serialización puede ser complejo. Pero, afortunadamente, no es necesario para serializar todo en su programa, lo más a menudo sólo los mensajes de protocolo son serializados, que a menudo son estructuras llanura de edad. Así que no es necesario los complejos trucos que he mencionado anteriormente con demasiada frecuencia.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top