Visualizzazione dei risultati da 1 a 6 su 6
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2007
    Messaggi
    40

    [c++] Serializzazione/Deserializzazione strutture dati

    Ciao a tutti,
    ho un problema con la serializzazione di una struttura dati.
    Per realizzare la serializzazione trasformo una struttura in array di byte e la invio sulla rete con la funzione memcpy... Il problema secondo me è dovuto al fatto che voglio inviare un vettore... ma nn so come cambiare la cosa... c'è qualcuno che può darmi una mano??? Allego il codice

    codice:
    #include <vector>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    using namespace std;
    
    #include "JNIStruct.h"
    
    typedef char * blockId;
    
    struct Block
    {
    	float startX;
    	float startY;
    	std::set <int> controlledVehicles;
    };
    
    struct Blocks{
    	std::vector <Block> cane;
    };
    
    void prin(char * data){
    
    	Blocks c;
    	memcpy(&c,data,sizeof(Blocks));
    	cout << " quello che "<< c.cane[0].startX<< " "<<c.cane[0].startY<< endl;
    	cout << " quello che "<< c.cane[1].startX<< " "<<c.cane[1].startY<< endl;
    
    }
    
    char * getStruct (){
    				 
    	Block b;
    	b.startX=32;
    	b.startY=33;
    
    	Block d;
    	d.startX=99;
    	d.startY=66;
    
    	Blocks bb;
    	bb.cane.push_back(b);
    	bb.cane.push_back(d);
    
    	char * oggetto= new char[sizeof(Blocks)];
    	memcpy(oggetto,&bb,sizeof(Blocks));
    
    	return oggetto;    
    }
    
    int main ( ) {
    
      char* pinki=getStruct();
      prin(pinki);
      system("pause");
      return 0;
    }

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Non puoi serializzare in quel modo strutture dati contenenti puntatori o classi; e nemmeno usare memcpy, memset o qualsiasi mem* su tipi non POD (per capirsi, sono quelli che si possono solo usare in C).
    Se poi li devi anche inviare in network, la cosa può complicarsi ancora di più.
    Un modo di procedere è dotare la struct Block di opportuni metodi.
    Ad esempio:
    codice:
    struct Block
    {
    	float startX;
    	float startY;
    	std::set <int> controlledVehicles;
    
        string serialize() const {
    		string v;
    		const char* m1 = reinterpret_cast<const char*>(&startX);
    		copy(&m1[0],&m1[sizeof(float)],back_inserter(v));
    
    		const char* m2 = reinterpret_cast<const char*>(&startY);
    		copy(&m2[0],&m2[sizeof(float)],back_inserter(v));
    		return v;
        }
    
        void deserialize(const string& v) {
    		std::size_t szFloat = sizeof(float);
    		char* m1 = reinterpret_cast<char*>(&startX);
    		copy(&v[0],&v[szFloat],m1);
    
    		char* m2 = reinterpret_cast<char*>(&startY);
    		copy(&v[szFloat],&v[szFloat + szFloat],m2);
        }
    };
    
    int main(int argc, char** argv) {
    	cout.sync_with_stdio(false);
    
    	Block b, b1;
    	b.startX = 15.1f;
    	b.startY = 27.4f;
    
    	string srlz = b.serialize();
    
    	b1.deserialize(srlz);
    
    	cout << b1.startX << " " << b1.startY << endl;
    }
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2007
    Messaggi
    40
    La cosa strana è che quando nel vettore non inserivo l'oggetto ma un puntatore a tale oggetto (Block*) la cosa, con qualche problema, funzionava... ma solo per il client che aveva generato il messaggio... quindi mi stai dicendo che il vettore non è POD e non posso inviarlo... l unica cosa che nn mi è chiara è che pensavo che l utilizzo di memcpy fosse lecito... in quanto facesse la copia bit a bit del contenuto....
    Ti ringrazio per la risposta...

  4. #4
    Utente di HTML.it L'avatar di KrOW
    Registrato dal
    Feb 2009
    Messaggi
    281
    Ciao . . . Il primo problema è che non ha senso "salvare" lo stato di un puntatore siccome avrà valori diversi tra differenti esecuzioni del programma (anche sulla stessa macchina). Anche per quanto riguarda la serializzazione dell' oggetto attraverso memcpy si hanno dei problemi dovuti soprattutto dall' ordinamento dei byte utilizzato dalla macchina (due macchine possono utilizzare due tipi d' ordinamento diversi) e dall' allineamento dei dati di una struttura (e qui si ha anche l' influenza del compilatore) . . .
    C++ 4ever
    496e2062696e6172696f206e6f6e2063692061767265737469 206e656d6d656e6f2020726f7661746f203a29

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2007
    Messaggi
    40
    Grazie per il chiarimento... tuttavia, shodan ha dimenticato il la serializzazione di controlledVehicles... che è un vettore a questo punto conviene scorrere tutti gli elementi del vettore e fare la serializzazione di ogni singolo elemento??? Inoltro a me interessa inviare una lista di oggetti Block... quindi dovrei fare la concatenazione di + Block ad esempio "string(Block1)-string(Block2)"... ogni consiglio è ben accetto in quanto nn pensavo di dover programmare così a basso livello...

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Non l'ho dimenticato, solo che nel tuo codice non c'era nessun riferimento a quel set e quindi non l'ho messo. Inoltre il mio era solo uno spunto per farti capire il problema, non voleva essere una soluzione definitiva.
    Per quanto riguarda il set in se, devi fare un ciclo e serializzare elemento per elemento; e, viceversa, deserializzare elemento per elemento. Da notare che questo lo dovresti fare anche con i puntatori, altrimenti ti verrebbe salvato il valore del puntatore, non quello a cui punta.

    Per l'ultima domanda. Una volta serializzato l'oggetto in una stringa, puoi sommarle e inviare il tutto, ma poi come discrimini due strutture diverse? Non puoi fare sizeof(Block) perché la dimensione della struttura differisce dai singoli valori serializzati. Dovresti quanto meno inviare la stringa serializzata + la dimensione della stringa serializzata.
    Ad esempio (riprendendo quanto postato):
    codice:
        std::size_t lenSrlz = srlz.size();
        string finalSrlzString(reinterpret_cast<char*>(&lenSrlz),sizeof( std::size_t ) );
        finalSrlzString += srlz;
        // send(finalSrlzString.c_str(),finalSrlzString.size() );
    I primi quattro byte indicano quanto è lunga la stringa che dovrai leggere e riconvertire, il resto è la struttura serializzata.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.