visual studio - C++ MFC SQLite sqlite3_exec callback

visual studio - C++ MFC SQLite sqlite3_exec callback

本文关键字:sqlite3 exec callback SQLite MFC studio C++ visual      更新时间:2023-10-16

所以我尝试在Visual Studio 2010中使用带有MFC对话的SQLite。我不清楚如何使用回调函数将查询的结果保存到变量m_Results中,该查询试图统计数据库中的表数。有没有这样做,或者我有没有访问nTables变量?

static int callback(void *data, int argc, char **argv, char **azColName){
    int i;
    fprintf(stderr, "%s: ", (const char*)data);
    data = argv[0];
    return 0;
}
BOOL CDBpracticeDlg::OnInitDialog(){
    ...
    // TODO: Add extra initialization here
    sqlite3 *db;
    char *zErrMsg = 0;
    int rc;
    char *sql;
    const char* data = "Callback function called";
    rc = sqlite3_open("structInfo_Test.db", &db);
    if( rc ){
        fprintf(stderr, "Can't open database: %sn", sqlite3_errmsg(db));
        return(0);
    }else{
        fprintf(stderr, "Opened database successfullyn");
    }
    /* Create SQL statement */
    sql = "Select Count(*) as nTables FROM sqlite_master where type='table';";
    /* Execute SQL statement */
    rc = sqlite3_exec(db, sql, callback, &m_Results, &zErrMsg);
    if( rc != SQLITE_OK ){
        char error[200];
        strcpy(error,"SQL error: ");
        strcat(error,zErrMsg);
        m_Results = error;
        fprintf(stderr, "SQL error: %sn", zErrMsg);
        sqlite3_free(zErrMsg);
    }else{
        fprintf(stdout, "Operation done successfullyn");
    }
    UpdateData(FALSE);
    sqlite3_close(db);
    return TRUE;  // return TRUE  unless you set the focus to a control
}

sqlite3_exec API的回调在很大程度上文档不足。事实上,它声称有误导性的参数名称,也没有多大帮助。提供更自然的形式参数名称有很大帮助:

static int callback(void* context,  // user-provided object (4th param to sqlite3_exec)
                    int columnCount,      // number of columns
                    char** columnValues,  // array of column values as C-style strings
                    char** columnName)    // array of column names as C-style strings

要从callback更新m_Results对象,只需将上下文强制转换为正确的类型,然后使用:

static int callback(void* context, int columnCount,
                    char** columnValues, char** columnNames) {
    CMyType& results = *static_cast<CMyType*>(context);
    // Use 'results' which is a reference to 'm_Results'.
    for (int index = 0; index < columnCount; ++index) {
        // Assuming CMyType has operator+=(const char*) (like a CString)
        results += columnNames[index];
        results += ": ";
        results += columnValues[index];
    }
    // Return 0 to continue invoking the callback for the remaining rows in the result
    // set. Returning non-zero will terminate the callbacks, and sqlite3_exec()
    // returns SQLITE_ABORT.
    return 0;

作为替代方案,您可以将this代替&m_Results传递给sqlite3_exec(),并从回调中调用一个公共类成员:

static int callback(void* context, int columnCount,
                    char** columnValues, char** columnNames) {
    CDBpracticeDlg* obj = static_cast<CDBpracticeDlg*>(context);
    // Delegate callback to class member implementation
    return obj->MyCallback(columnCount, columnValues, columnNames);
}
...
rc = sqlite3_exec(db, sql, callback, this, nullptr);