CharybdeBE
CharybdeBE

Reputation: 1843

Sqlite3 and C, Populate a structure with the callback

I'm quiet new with the use of Sqlite and i would like to use the callback in the exec function to populate a structure (using the 4th parameter as pointer to the structure)

I've tried this :

static int buildHost(void * pHost, int argc, char **argv, char **azColName){
   int i;
   struct host* host = malloc(sizeof(struct host));
   struct snmp_info* inf = malloc(sizeof(struct snmp_info));
   host->info = inf;
   for(i=0; i<argc; i++){
    if(strcmp(azColName[i], "ip") == 0)
         host->ip = argv[i] ? argv[i] : NULL;
    else if (strcmp(azColName[i], "port")  == 0)
         host->info->port = argv[i] ? argv[i]  : NULL;
    else if (strcmp(azColName[i], "community")  == 0)
         host->info->community = argv[i] ? argv[i]  : NULL;
    else if (strcmp(azColName[i], "SNMPv")  == 0)
         host->info->SNMPv = argv[i] ?atoi( argv[i] ) : 0;
    else if (strcmp(azColName[i], "auth_protocol")  == 0)
         host->info->auth_protocol = argv[i] ? argv[i]  : NULL;
    else if (strcmp(azColName[i], "password")  == 0)
         host->info->password = argv[i] ? argv[i]  : NULL;
    else if (strcmp(azColName[i], "encryption")  == 0)
         host->info->encryption = argv[i] ? argv[i]  : NULL;
    else if (strcmp(azColName[i], "encryption_passwd")  == 0)
         host->info->encryption_passwd = argv[i] ? argv[i]  : NULL;
   }

   pHost = &host; //Seems to be the problem line

   printf("\n");
   return 0;
}

And i call the function like that :

struct host* toRet;
sqlite3_exec(db, request, buildHost, &toRet,0);

I would add that my code compile and that if i do some printf in the callback function i have the good data (i made the select on a key so i can only have one answer or none) But when i try in the calling function to do

printf("%s", toRet->ip); 

i've got a segfault

Thanks in advance, it's probably easy for someone who is used with the library but i'm not and every tutorial that i've found don't use the first argument of the callback

Have a nice day

Upvotes: 0

Views: 890

Answers (3)

LS_ᴅᴇᴠ
LS_ᴅᴇᴠ

Reputation: 11161

Your prototype and assignment are not correct::

static int buildHost(struct host**pHost, int argc, char **argv, char **azColName) {
   ...
   *pHost = host;
   ...
}

Upvotes: 0

CharybdeBE
CharybdeBE

Reputation: 1843

Hello the answer was a mix of what mfro as said about pointer and CL. about the new interface But the big error was that i did not have allocated the char* so they disapear after the call.

Now here is my two function corrected for people that may be in my case :

static struct host* buildHost(sqlite3_stmt* stmt){
   int i;
   struct host* host = malloc(sizeof(struct host));
   struct snmp_info* inf = malloc(sizeof(struct snmp_info));
      host->info = inf;
   for(i=0; i < 9; i++){
    char* colName = (char*)sqlite3_column_name(stmt, i);
    char* content = (char*)sqlite3_column_text(stmt, i);
    char* content2; 
    int len;

    if(content){
        len = strlen(content);
        content2 = malloc(sizeof(char) * len);
        strcpy(content2, content);

    }


    if(strcmp(colName, "ip") == 0)
        host->ip = content ? content2 : NULL;
    else if (strcmp(colName, "port")  == 0)
         host->info->port = content ? content2 : NULL;
    else if (strcmp(colName, "community")  == 0)
         host->info->community = content ? content2 : NULL;
    else if (strcmp(colName, "SNMPv")  == 0)
         host->info->SNMPv = content ? atoi(content) : 0;
    else if (strcmp(colName, "auth_protocol")  == 0)
         host->info->auth_protocol = content ? content2  : NULL;
    else if (strcmp(colName, "password")  == 0)
         host->info->password = content ? content2  : NULL;
    else if (strcmp(colName, "encryption")  == 0)
         host->info->encryption = content ? content2 : NULL;
    else if (strcmp(colName, "encryption_passwd")  == 0)
         host->info->encryption_passwd = content ? content2  : NULL;


   }

    return host;
}

struct host* getHost(char* ip, sqlite3* db){
    sqlite3_stmt *stmt;
    char request[1024] = "SELECT * FROM snmp_info WHERE ip= \"" ;
    struct host* toRet = malloc(sizeof(struct host));
    int rc;
    strcat(request, ip);
    strcat(request, "\";");

    rc = sqlite3_prepare_v2(db, request, -1, &stmt, NULL);

    if (rc != SQLITE_OK) {
        printf("error: %s!\n", sqlite3_errmsg(db));
        return NULL;
        }

    rc = sqlite3_step(stmt);
    if(rc == SQLITE_DONE || rc != SQLITE_ROW)
        return NULL;
    toRet = buildHost(stmt);
    sqlite3_finalize(stmt);


    return toRet;
}

Upvotes: 0

mfro
mfro

Reputation: 3335

I don't know that particular API, but with

pHost = &host;

you are returning the address of a local variable. This is destroyed after the call returns. What you probably wanted is

* (struct host *) pHost = host

since this is already a pointer.

Upvotes: 1

Related Questions