Marshalling i UnMarshalling structs amb punters

September 6, 2007 – 1:45 pm

Encara recordo que en l'últim projecte de la facultat varem forçar les estructuctures declarades amb C a un conjunt fix de bytes, per evitar problemes amb la serializació d'aquestes - i posterior desserialització - per enviar.les via una capa de red independent.

El que podiem tenir :

typedef struct exemple_t
{
char * a;
char * b;
};

Es convertia senzilalment amb :

typedef struct exemple_t
{
char a[MAX_BUFFER];
char b[MAX_BUFFER];
};

Mitjançant aquesta petita modificació evitavem el que nosaltres en un principi varem creure que seria una operació certament complicada. Aquesta modificació clar no estava excempte de danys col.laterals, lús ineficient de l'espai.

A dia d'avui i per "culpa" de APDN i la serialització de dades sobre un hash de les libdb de Berkeley, m'he trobat amb un problema molt semblant, i que he resolt de forma satisfactoria mitjançant estructures amb punters i sense tenir que redefinir aquestes mitjançant tamanys fixes de dades. A aquesta operació se l'anomena tècnicament Marshalling i Unmarshalling.

Com ho fem doncs ?

Imaginem altre vegada una estructura del tipus següent :

typedef struct u_t
{
char * a;
char * b;
}

Per poder serializar aquesta informació en un buffer només ens cal treballar una mica amb els punters i les seves longituds.

int marshallingdata(char *, char *b)
{
char * buffer;
int sizeof_buffer;
// marshaling
sizeof_buffer = strlen(a) + strlen(b) + 2;
buffer = (char *) malloc(sizeof_buffer);

memset(buffer, 0, sizeof_buffer);

memcpy(buffer, name, strlen(name) + 1)
buflen = strlen(name) + 1);
memcpy(buffer + buflen, file_app, strlen(file_app) + 1);

data.data = buffer
data.size = sizeof(sizeof_buffer);

// put to data base
err = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE | DB_NODUPDATA);

...

}

En el camí invers, el unmarshaling o desserialització utilizem també la informació implicita - tamany de dades - i explicita - tamany de les cadenes - per poder crear una estructura d'un buffer

int unmarshallingdata(u_t **p)
{

// get from data base

err= dbp->get(dbp, buffer ...)

// unmarshalling

*p = (u_t *) malloc (sizeof(u_t));
*p->a = (char *) malloc ( strlen(buffer) + 1);
*p->b = (char *) malloc ( strlen(buffer + strlen(*p->a) + 1) + 1);
memset(*p->a, 0, strlen(buffer) + 1)
strncpy(*p->a, buffer, strlen(buffer))
memset(*p->b, 0, strlen(buffer + strlen(*p->a) + 1) + 1)
strncpy(*p->b, buffer + strlen(*p->a) + 1, strlen(buffer + strlen(*p->a) +
1))
....
....
free(buffer)

}

Post a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word