The example I listed came from the SleepyCat documentation http://www.sleepycat.com/d
- Steve Sarette
Documentation Engineer
Sleepycat Software
Mr. Sarette provided the following abreviated example. However when I added in the database support I could not retrieve the data from the database.
#include <db.h>
#include <string.h>
#define MAXBUFFER 300
#define MAXSTRING 100
/* Declare our struct */
struct example_structure {
float myFloat;
int myInt;
char *myString;
};
typedef struct example_structure EXAMPLE_STRUCTURE;
/*
* Program to illustrate marshalling and unmarshalling structures.
*
* Marshalling is the process of moving the contents of a structure's
* fields into a single contiguous memory location. This is done so that
* the structure can be stored in a Berkeley DB database.
*
* Unmarshalling is performed to take data retrieved from a Berkeley DB database
* and place it back into the structure so that it can be used by the
* application.
*/
int
main(int argc, char *argv[])
{
DBT sampleDBT; /* The Berkeley DB data structure that we use to store data
* in a database. Typically there are two of these for
* every database record, one for a key and one for the
* data. In this case, we need only one DBT for
* illustration purposes.
*/
EXAMPLE_STRUCTURE myStruct; /* The structure we want to store */
EXAMPLE_STRUCTURE newStruct; /* The structure we want to place data into */
int buffer_length; /* The amount of data stored in our buffer */
u_int32_t buffer[MAXBUFFER]; /* The buffer itself */
u_int32_t *bufferPtr; /* A pointer into the buffer */
/* First, we fill in our structure's data fields */
myStruct.myFloat = 3.04;
myStruct.myInt = 200;
/* malloc space for the string */
myStruct.myString = (char *)malloc(MAXSTRING * sizeof(char));
/* Copy a string into that space. */
strncpy(myStruct.myString,
/*
* In order to store the data for this structure, we must make sure that
* all its data is lined up in a single contiguous block of memory -- that
* is, in a single buffer. We also need to know how much data was put into
* that buffer. To do this, we copy the structure's data into the buffer.
* This is the actual marshalling process.
*
* Note that the order we use to copy the data is not important, except
* that we have to make sure that we unmarshall in the same order. Here
* we mix things up a bit in order to illustrate the concept.
*
* Notice that we keep track of how much data we've placed in the buffer as
* we go. Also, take care to copy each new bit of data to the end of the
* buffer, so as to not overwrite any data previously placed there.
*/
/* Initialize the buffer */
memset(&buffer, 0, MAXBUFFER);
/* Copy the struct's int into the buffer */
bufferPtr = &buffer[0];
memcpy(bufferPtr, &(myStruct.myInt), sizeof(int));
buffer_length = sizeof(int);
/* Copy the struct's string into the buffer */
bufferPtr = &buffer[buffer_length];
memcpy(bufferPtr, myStruct.myString,
(strlen(myStruct.myString)
buffer_length += (strlen(myStruct.myString)
/* Copy the struct's float into the buffer */
bufferPtr = &buffer[buffer_length];
memcpy(bufferPtr, &(myStruct.myFloat), sizeof(float));
buffer_length += sizeof(float);
/*
* We now have a buffer that contains all our data. We also have the size of
* the data contained in that buffer. We can use this buffer with our DBT:
*/
sampleDBT.data = buffer;
sampleDBT.size = buffer_length;
/*
* We can now pass the data DBT to a DB->put() or DBC->c_put() call for
* storage in the database. We won't show that here.
*/
/*
* Upon retrieval from the database (again, we don't show the actual
* database get() activity), the DBT's data field is pointing to
* a void * buffer that contains exactly the data that we marshalled into
* our buffer above. We now need to only unmarshall that data. To do this,
* we have to remember the order in which we originally marshalled the
* data.
*/
/*
* Note that we're reusing the same DBT for unmarshalling process as we used
* to marshall the data. In real-world usage, the two would be different
* as they would almost certainly be declared in different scopes.
*/
bufferPtr = sampleDBT.data;
/* First, find the int (the first bit of data that we stored) */
newStruct.myInt = *((int *)bufferPtr);
bufferPtr += sizeof(int);
/* Next, the string */
newStruct.myString = (char *)bufferPtr;
bufferPtr += (strlen(newStruct.myString
/* And finally, the float */
newStruct.myFloat = *((float *)bufferPtr);
/*
* Now we can print everything out to prove that the marshalling process
* worked
*/
printf("Original structure:\n");
printf("\tmyInt: %i, \tmyFloat: %f\n", myStruct.myInt, myStruct.myFloat);
printf("\tmyString: %s\n", myStruct.myString);
printf("\nNew structure (after marshalling and unmarshalling:\n");
printf("\tmyInt: %i, \tmyFloat: %f\n", newStruct.myInt, newStruct.myFloat);
printf("\tmyString: %s\n", newStruct.myString);
/* Cleanup */
free(myStruct.myString);
return(0);
}
Main Topics
Browse All Topics





by: fridomPosted on 2004-05-07 at 00:42:41ID: 11012702
Well I don't know why you have omitted the declaration of info.
;
Whis is the datastructure you're working on.
I've written this some time ago:
typedef struct st_adr {
struct st_adr_lpVtbl *lpVtbl;
struct st_adr_data *data;
size_t data_size;
} ST_ADR;
struct st_adr_lpVtbl {
int (*save)(ST_ADR*);
int (*clone)(ST_ADR*, ST_ADR*);
int (*equal) (ST_ADR*, ST_ADR*);
char * (*get_name) (ST_ADR*);
char * (*get_first_name) (ST_ADR*);
char * (*get_street) (ST_ADR *);
char * (*get_city) (ST_ADR *);
int (*get_zip) (ST_ADR*);
void * (*get_by_idx) (ST_ADR*, int);
char * (*get_entry_by_idx) (ST_ADR*, int);
void (*set_entry_by_idx) (ST_ADR*, int, char*);
void (*set_by_idx) (ST_ADR*, int, void*);
void (*set_name) (ST_ADR *, char*);
void (*set_first_name)(ST_ADR *, char*);
void (*set_street)(ST_ADR *, char*);
void (*set_city)(ST_ADR *, char*);
void (*set_zip) (ST_ADR*, int);
void (*st_test) (char*);
};
extern struct st_adr_lpVtbl st_adr_vtable;
struct st_adr_data {
char name[NAME_MAX];
char first_name[NAME_MAX];
char street[STREET_MAX];
char city [CITY_MAX];
int zip;
This are the data-structures I wanted to save. Now the save functions looks like this:
int adr_save_record (ST_ADR *record){
assert(record);
DB *hdb = NULL;
DBT key = {0};
DBT data = {0};
int i_rval = 0;
i_rval = adr_open_db(&hdb);
if (0 != i_rval ) {
return FAULT;
}
key.data = record->get_name();
key.size = strlen(record->get_name())
/* Key is the name field of an Adr structure */
data.data = record->data;
data.size = record->data_size;
i_rval = hdb->put(hdb, NULL,
&key, &data, 0);
if (i_rval > 0){
hdb->err (hdb, i_rval, "Problems puttting value", NULL);
i_rval = hdb->close(hdb,0);
return FAULT;
}
i_rval = hdb->close(hdb,0);
return 0;
}
That's all what is needed to write structures to the Database.
IMHO it pays of to spend some time in the documentation. I propose to check out the tutorial especially.
Regards
Friedrich