Cite / C ++中的SQLite。 sqlite3_exec:回调函数中的参数集指向空字符串

我正在尝试一些非常基本的东西 – 使用SQLite的C / C ++接口返回SELECT语句的结果。 我的数据表只有两个字段 – 键(varchar)和值(文本)。

鉴于密钥,我的目标是通过查询SQLite数据库来返回值。 我传递给* sqlite3_exec * – * select_callback *函数以及param (char *)。 param在* select_callback *中成功设置为正确的值。 但是,在调用* sqlite3_exec * param指向空字符串后(尽管指向相同的内存)。

知道出了什么问题以及如何解决这个问题? * sqlite3_exec *在幕后为param释放内存吗?

先感谢您!

 // given the key tid returns the value void getTypeByID(sqlite3 * db, string tid) { string sql_exp_base = "select value from Data where key=''"; int len = (int)sql_exp_base.size() + (int)tid.size() + 10; char * sql_exp = new char[len]; sprintf(sql_exp, "select value from Data where key='%s'", tid.data()); sql_exec(db, sql_exp); } // This is the callback function to set the param to the value static int select_callback(void * param, int argc, char **argv, char **azColName) { if(argc == 0) return 0; char * res = (char *)param; res = (char *) realloc(res, sizeof(*res)); res = (char *) malloc(strlen(argv[0]) + 1); strcpy(res, argv[0]); printf("%s\n", res); // {"name": "Instagram Photo", url: "http://instagram.com"} return 0; } // execute the SQL statement specified by sql_statement void sql_exec(sqlite3 * db, const char * sql_statement) { char * zErrMsg = 0; char * param = (char *)calloc(1, sizeof(*param)); int rc = sqlite3_exec(db, sql_statement, select_callback, param, &zErrMsg); printf("%s\n", param); 

param应该是{“名字”:“Instagram照片”,url:“http://instagram.com”},但是因为某些原因它是空的!

  if(rc != SQLITE_OK) { fprintf(stderr, "SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } } 

您正在将指向新分配的内存的指针写入res ,但该变量是select_callback的局部变量,因此sql_exec将不知道它。 这同样适用于param参数:它只是sqlite3_exec的第四个参数的副本。

为了确保能够看到对字符串的更改,您必须将指针传递给字符串本身(这是C中的指针,或者可能是C ++中的string对象),类似于错误消息。 对于C:

 char *result_str = ...; rc = sqlite3_exec(..., &result_str, ...); ... int callback(void *param, ...) { char **result_str = (char **)param; *result_str = (char *)realloc(*result_str, ...); strcpy(*result_str, ...); } 

注意:tid字符串包含引号或其他控制字符时,或者当您尝试搜索Bobby表时,您将遇到问题。 使用sqlite3_mprintf格式化和分配SQL字符串,或者更好地使用参数 。

我尝试了最后一个答案,它对我有用:我创建了一个指针作为char值的指针,并从void变量插入指针的指针

 #include  #include  #include  #include  #include  int callback(void *data,int argc,char *argv[],char **azcolname) { int i=0; char **result_str = (char **)data; *result_str = (char *)calloc(strlen(argv[0]),sizeof(char)); strcpy(*result_str,argv[0]); return 0; } int main(int argc,char *argv[]) { sqlite3 *conn; int c=0; char *ofile=NULL; char *tsql_stmt=NULL; int res=0; char *zErrMsg = 0; char *data=NULL; while((c = getopt(argc , argv ,"f:")) != -1) { switch (c) { case 'f': ofile = optarg; break; default: fprintf(stderr,"worng argument provided\n"); break; } } if (!ofile) { fprintf(stderr,"no output file (-f) given\n"); exit(1); } sqlite3_open(ofile,&conn); tsql_stmt = calloc(80,sizeof(char)); strcpy(tsql_stmt,"SELECT count(*) FROM sqlite_master WHERE type='table' AND name='"); strcat(tsql_stmt,"mytest"); strcat(tsql_stmt,"\'"); //running the query //printf("%s\n",tsql_stmt); res = sqlite3_exec(conn,tsql_stmt,callback,&data, &zErrMsg); if ( res != SQLITE_OK ) { fprintf(stderr, "SQL error: %s\n", zErrMsg); sqlite3_free(zErrMsg); } else{ if ( atoi(data) != 1) fprintf(stderr, "unable to find the requested table\n"); else printf("the Operation found the requested table in the database\n"); } free(data); sqlite3_close(conn); return 0; }