Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialization of struct

Suppose i have a struct whose member values i want to send over the network to another system using winsock 2. I'm using C++ language. How do i convert it to char * keeping in mind that the struct has to be serialized before sending and also how do i deserialize the char * into struct at the other end? I found boost serialization as a suggestion to similar question but can anyone illustrate with a small code snippet for both serialization and deserialization ?

This question might seem very basic but the other answers to the related posts did not help much.

like image 964
Vigo Avatar asked May 14 '13 12:05

Vigo


People also ask

Can struct be serialized?

Yes, you can. I just did so with the following code. [Serializable] public struct TestStruct { public int Value1 { get; set; } public int Value2 { get; set; } public string Value3 { get; set; } public double Value4 { get; set; } } TestStruct s1 = new TestStruct(); s1.

What is serialization of structured data?

Serialization is the process of converting a data object—a combination of code and data represented within a region of data storage—into a series of bytes that saves the state of the object in an easily transmittable form.

What is serialization in C?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.

What is tree serialization?

Serialization is to store tree in a file so that it can be later restored. The structure of tree must be maintained. Deserialization is reading tree back from file. Recommended Problem. Serialize and Deserialize a Binary Tree.


3 Answers

Following example shows a simplest way to serialize struct into char array and de-serialize it.

#include <iostream>
#include <cstring>

#define BUFSIZE 512
#define PACKETSIZE sizeof(MSG)

using namespace std;

typedef struct MSG
{
    int type;
    int priority;
    int sender;
    char message[BUFSIZE];
}MSG;

void serialize(MSG* msgPacket, char *data);
void deserialize(char *data, MSG* msgPacket);
void printMsg(MSG* msgPacket);

int main()
{
    MSG* newMsg = new MSG;
    newMsg->type = 1;
    newMsg->priority = 9;
    newMsg->sender = 2;
    strcpy(newMsg->message, "hello from server\0");
    printMsg(newMsg);

    char data[PACKETSIZE];

    serialize(newMsg, data);

    MSG* temp = new MSG;
    deserialize(data, temp);
    printMsg(temp);

    return 0;
}

void serialize(MSG* msgPacket, char *data)
{
    int *q = (int*)data;    
    *q = msgPacket->type;       q++;    
    *q = msgPacket->priority;   q++;    
    *q = msgPacket->sender;     q++;

    char *p = (char*)q;
    int i = 0;
    while (i < BUFSIZE)
    {
        *p = msgPacket->message[i];
        p++;
        i++;
    }
}

void deserialize(char *data, MSG* msgPacket)
{
    int *q = (int*)data;    
    msgPacket->type = *q;       q++;    
    msgPacket->priority = *q;   q++;    
    msgPacket->sender = *q;     q++;

    char *p = (char*)q;
    int i = 0;
    while (i < BUFSIZE)
    {
        msgPacket->message[i] = *p;
        p++;
        i++;
    }
}

void printMsg(MSG* msgPacket)
{
    cout << msgPacket->type << endl;
    cout << msgPacket->priority << endl;
    cout << msgPacket->sender << endl;
    cout << msgPacket->message << endl;
}
like image 52
Amith Chinthaka Avatar answered Sep 18 '22 11:09

Amith Chinthaka


You can just do

struct MyStruct {

    int data;
    char* someNullTerminatedName; // Assuming not larger than 1023 chars

    std::ostream& serialize(std::ostream& os) const {
        char null = '\0';
        os.write((char*)&data, sizeof(data));
        os.write(someNullTerminatedName, strlen(someNullTerminatedName));
        os.write(&null, 1);
        return os;
    }
    std::istream& deserialize(std::istream& is) {
        char buffer[1024];
        int i = 0;
        is.read((char*)&data, sizeof(data));
        do { buffer[i] = is.get(); ++i; } while(buffer[i] != '\0');
        if (someNullTerminatedName != NULL) free(someNullTerminatedName);
        someNullTerminatedName = (char*)malloc(i);
        for (i = 0; buffer[i] != '\0'; ++i) {
            someNullTerminatedName[i] = buffer[i];
        }
        return is;
    }
};

It's up to you to take care of endianness and differences in size of ints and whatnot.

Example:

MyStruct foo, bar;
std::stringstream stream;
foo.serialize(stream);
// ... Now stream.str().c_str() contains a char* buffer representation of foo.
// For example it might contain [ 1f 3a 4d 10 h e l l o w o r l d \0 ]
bar.deserialize(stream);
// ... Now bar is a copy, via a serial stream of data, of foo.

If you have a socket library that exposes its interface via C++ iostreams then you don't even need the stringstream.

like image 38
rwols Avatar answered Sep 20 '22 11:09

rwols


You can also have a look at Protocol Buffers from Google which is a platform/language independent library for sending data between hosts.

However, the paradigm is shifted towards writing the protocol first and then fitting your data structures into it. The advantage of this though is that it forces your software architecture to fit well with simple data types.

like image 25
Nick Avatar answered Sep 19 '22 11:09

Nick