C++: casting to void* and back
* ---Edit - now the whole sourse*
When I debug it on the end, "get" and "value" have different values! Probably, I convert to void* and back to User the wrong way?
#include <db_cxx.h>
#include <stdio.h>
struct User{
User(){}
int name;
int town;
User(int a){};
inline int get_index(int a){
return town;
} //for another stuff
};
int main(){
try {
DbEnv* env = new DbEnv(NULL);
env->open("./",
DB_CREATE | DB_INIT_MPOOL | DB_THREAD |
DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER | DB_INIT_LOG, 0);
Db* datab = new Db(env, 0);
datab->open(NULL, "db.dbf", NULL, DB_BTREE, DB_CREATE | DB_AUTO_COMMIT, 0);
Dbt key, value, get;
char a[10] = "bbaaccd";
User u;
u.name = 1;
u.town = 34;
key.set_data(a);
key.set_size(strlen(a) + 1 );
value.set_data((void*)&u);
value.set_size(sizeof(u));
get.set_flags(DB_DBT_MALLOC);
DbTxn* txn;
env->txn_begin(NULL, &txn, 0);
datab->put(txn, &key, &value, 0);
datab->get(txn, &key, &get, 0);
txn->commit(0);
User g;
g = *((User*)&get);
printf("%d", g.town);
getchar();
return 0;
}catch (DbException &e){
printf("%s", e.what());
getchar();
}
solution
create a kind of "serializator" what would convert all POD's into void* and then will unite these pieces
PS Or I'd rewrite User into POD type and everything will be all right, I hope.
Add
It's strange, but... I cast a defenetly non-pod object to void* and back (it has std::string inside) and it's all right (without sending it to the db and back). How could it be? And after I cast and send 'trough' db defenetly pod object (no extra methods, all members ar开发者_StackOverflow社区e pod, it's a simple struct {int a; int b; ...}) I get back dirted one. What's wrong with my approach?
Add about week after first 'add'
Damn... I've compiled it ones, just for have a look at which kind of dirt it returnes, and oh! it's okay!... I can't ! ... AAh!.. Lord... A reasonable question (in 99.999 percent of situations right answer is 'my', but... here...) - whos is this fault? My or VSs?
Unless User
is a POD this is undefined in C++.
Edit:
Looking at db_cxx.h, aren't you supposed to do call get_doff()
, get_dlen()
, and get_data()
or something on Dbt
instead of just casting (and assigning) it to the user type?
Since there is no check of the return value of put(), it could well be there is an error which prevented updating. The documentation indicates quite a few error condtions:
You are almost definitely NOT supposed to cast 'get' directly to a User. Instead, extract the data you stored and then cast that. We can't know for sure unless you share with us the definition of Dbt. Making a guess, based on what we can see:
datab->get(txn, &key, &get, 0);
void* data = get.get_data();
User g = *((User*)data);
Tell us more about Dbt and we can probably help you out more.
I would do something like this:
User user;
std::stringstream dbStotrStream;
dbStoreStream << user; // Serialize user
std::string dbStore(bdStoreStream.str());
value.set_data(dbStore.c_str());
value.set_size(dbStore.lenght());
//// Put in DB
Then extracting it would look like this:
//// Get from DB
std::string dbStore(get.get_data(),get.get_date() + get.get_size());
std::stringstream dbStoreStream(dbStore);
User outUser;
dbStoreStream >> outUSer;
精彩评论