Domanda

Ho una piccola gerarchia di oggetti che ho bisogno di serializzare e trasmettere tramite una connessione socket. Ho bisogno di entrambi serializzare l'oggetto, quindi deserializzare esso sulla base di che tipo è. C'è un modo semplice per fare questo in C ++ (in quanto v'è in Java)?

Ci sono ++ esempi di codice serializzazione linea C o tutorial?

Modifica Giusto per essere chiari, sto cercando i metodi sulla conversione di un oggetto in un array di byte, poi di nuovo in un oggetto. Posso gestire la trasmissione presa.

È stato utile?

Soluzione

A proposito di serializzazione, il aumentare serializzazione API viene in mente. Per quanto riguarda la trasmissione dei dati serializzati in rete, mi piacerebbe usare sia le prese di Berkeley o il ASIO biblioteca .

Modifica
Se si desidera serializzare gli oggetti a un array di byte, è possibile utilizzare il serializzatore spinta nel modo seguente (preso dal sito 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)
    {}
};

serializzazione Attuale è quindi abbastanza facile:

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

deserializzazione funziona in modo analogo.

Ci sono anche meccanismi che consentono di gestire la serializzazione di puntatori (strutture dati complesse come alberi ecc non sono un problema), classi derivate e si può scegliere tra la serializzazione binaria e il testo. Inoltre tutti i contenitori STL sono supportati dalla scatola.

Altri suggerimenti

In alcuni casi, quando si tratta di tipi semplici, si può fare:

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

Va bene come un proof-of-concept o di primo progetto, in modo che altri membri del team possono continuare a lavorare su altre parti.

Ma prima o poi, di solito prima , questo ti fa male!

Si esegue in problemi con:

  • verrà danneggiato tavoli puntatore virtuale.
  • Puntatori (per dati / soci / funzioni) sarà danneggiato.
  • Le differenze di imbottitura / allineamento su macchine diverse.
  • problemi
  • Big / Little-Endian byte di ordinazione.
  • Le variazioni nella realizzazione del galleggiante / doppia.

(Inoltre è necessario sapere cosa si sono disimballaggio nel sul lato ricevente.)

È possibile migliorare su questo sviluppare il proprio smistamento metodi / deserializzazione per ogni classe. (Idealmente virtuale, in modo che possano essere esteso in sottoclassi.) Poche semplici macro vi permetterà di scrivere diversi tipi di base abbastanza rapidamente in un grande ordine / little-endian neutro.

Ma questo genere di lavoro sporco è molto meglio, e più facilmente, gestite tramite di spinta biblioteca serializzazione .

La serializzazione significa trasformare l'oggetto in dati binari. Mentre deserializzazione significa ricreare un oggetto dai dati.

Quando la serializzazione si sta spingendo in un vettore di byte uint8_t. Quando deserializzazione, si sta leggendo byte da un vettore uint8_t.

Ci sono certamente i modelli si possono impiegare durante la serializzazione roba.

Ogni classe serializzabile dovrebbe avere una serialize(std::vector<uint8_t> &binaryData) o funzione simile signatured che scriverà sua rappresentazione binaria nel vettore disponibile. Poi questa funzione potrebbe passare questo vettore verso il basso per le sue funzioni di serializzazione di questo utente in modo da poter scrivere le loro cose in esso troppo.

Poiché la rappresentazione di dati può essere differente in differenti architetture. Hai bisogno di trovare uno schema come rappresentare i dati.

Partiamo dalle basi:

serializzazione di dati interi

Basta scrivere i byte in po 'd'ordine endian. Oppure utilizzare la rappresentanza varint se le dimensioni contano.

La serializzazione in po 'd'ordine Endian:

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

deserializzazione da little endian:

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

serializzazione di dati a virgola mobile

Per quanto ne so IEEE 754 ha il monopolio qui. Non so di qualsiasi architettura tradizionale che userebbe qualcosa di diverso per i galleggianti. L'unica cosa che può essere diverso è l'ordine dei byte. Alcune architetture usano little endian, altri usano grande ordine endian byte. Questo significa che è necessario stare attenti che per voi ad alta voce i byte sul lato di ricezione. Un'altra differenza può essere manipolazione del denormal e infinito e valori NAN. Ma finché si evita di questi valori si dovrebbe essere OK.

serializzazione:

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

deserializzazione lo sta facendo a ritroso. Mente l'ordine dei byte della vostra architettura!

stringhe Serializzazione

In primo luogo è necessario concordare una codifica. UTF-8 è comune. Poi conservarlo in maniera lunghezza prefissata. Prima di memorizzare la lunghezza della stringa utilizzando un metodo già accennato, quindi scrivere la stringa di byte per byte

serializzazione di array.

Sono lo stesso di uno stringhe. Innanzitutto serializza un intero che rappresenta la dimensione della matrice quindi serializzare ogni oggetto in esso.

serializzazione di oggetti interi

Come ho detto prima che dovrebbe avere un metodo serialize che aggiungere contenuti ad un vettore. Per unserialize un oggetto, dovrebbe avere un costruttore che prende flusso di byte. Può essere un istream ma nel caso più semplice può essere solo un puntatore uint8_t di riferimento. Il costruttore legge i byte che vuole dal flusso e imposta i campi nell'oggetto. Se il sistema è ben progettato e serializzare i campi in ordine dei campi oggetto, si può semplicemente passare il torrente per costruttori del campo in una lista di inizializzazione e li hanno deserializzati nel giusto ordine.

Serializzazione grafi di oggetti

Per prima cosa è necessario assicurarsi se questi oggetti sono davvero qualcosa che si desidera serializzare. Non è necessario per serializzare loro se le istanze di questi oggetti presenti nella destinazione.

Ora hai scoperto è necessario serializzare quell'oggetto indicato da un puntatore. Il problema dei puntatori che esse sono valide solo l'nel programma che li utilizza. Non si può serializzare il puntatore, si dovrebbe smettere di usarli in oggetti. Invece di creare pool di oggetti. Questa piscina oggetto è fondamentalmente un array dinamico che contiene "scatole". Queste scatole hanno un conteggio di riferimento. conteggio di riferimento diverso da zero indica un oggetto vivo, zero indica uno slot vuoto. Quindi si crea puntatore intelligente simile alla shared_ptr che non memorizza il puntatore all'oggetto, ma l'indice nella matrice. È inoltre necessario essere d'accordo su un indice che denota il puntatore nullo, per esempio. -1.

In pratica quello che abbiamo fatto qui è sostituito i puntatori con indici di matrice. Ora, quando la serializzazione è possibile serializzare questo indice array come al solito. Non è necessario preoccuparsi di dove viene l'objecT sarà in memoria sul sistema di destinazione. Basta assicurarsi che essi hanno lo stesso pool di oggetti troppo.

Quindi abbiamo bisogno di serializzare le piscine oggetto. Ma quali? Beh quando si serializza un oggetto grafico non si serializzare solo un oggetto, si sta serializzazione di un intero sistema. Ciò significa che la serializzazione del sistema non deve partire dalla parti del sistema. Questi oggetti non devono preoccuparsi del resto del sistema, hanno solo bisogno di serializzare gli indici di matrice e il gioco è fatto. Si dovrebbe avere una routine di sistema serializzatore che orchestra la serializzazione del sistema e passeggiate attraverso le piscine degli oggetti rilevanti e serializzare tutti loro.

Sulla ricevente terminare tutti gli array un gli oggetti sono deserializzati, ricreando il grafico oggetto desiderato.

Serializzazione puntatori a funzione

Non conservare i puntatori nell'oggetto. Avere un array statico che contiene i puntatori a queste funzioni e memorizzare l'indice nell'oggetto.

Dal momento che entrambi i programmi hanno questa tabella compilata in themshelves, utilizzando solo l'indice dovrebbe funzionare.

Serializzazione tipi polimorfici

Dal momento che ho detto si dovrebbe evitare puntatori nei tipi serializzabili e si dovrebbe utilizzare indici di matrice invece, il polimorfismo semplicemente non può funzionare, perché richiede i puntatori.

Hai bisogno di lavorare intorno a questo con le etichette di tipo e sindacati.

Versioning

In cima a tutto quanto sopra. Si potrebbe desiderare diverse versioni del software di interoperare.

In questo caso ogni oggetto deve scrivere un numero di versione, all'inizio della loro serializzazione per indicare la versione.

Quando si carica l'oggetto dall'altra parte gli oggetti più recenti, forse in grado di gestire le rappresentazioni più anziani, ma i più grandi non possono gestire il più recente in modo che dovrebbe generare un'eccezione su questo.

Ogni volta che un qualcosa cambia, si dovrebbe urtare il numero di versione.


Quindi, per avvolgere questo, la serializzazione può essere complessa. Ma per fortuna non è necessario per serializzare tutto nel vostro programma, il più delle volte solo i messaggi di protocollo vengono serializzati, che spesso sono vecchie le strutture semplici. Quindi non hai bisogno di trucchi complessi che ho citato sopra troppo spesso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top