Using SQLite in C++: object function as a callback

2019-02-19 00:54发布

问题:

So, I am working on a side-project to keep my c++ skills fresh (it has been many years since I have done work in c++). I am working on something where I will be using SQLite. I have a wrapper around the SQLite code. One of the things I am noticing is that SQLite uses c-style callback functions in its sqlite3_exec(...) function.

I would like to have the callback function be an object method, as I would like it to be able to modify object variables but am unsure of how to do this exactly. I have checked other similar questions on stackoverflow but came away with nothing helpful.

Here is how I am declaring my wrapper class:

class DBAdapter
{
private:
    sqlite3* db;
    int getUserRecords(std::string);
    std::vector<USER_RECORD> records;

    int callbackSel(void*, int , char**, char**);

public:
    DBAdapter();
    ~DBAdapter();

    int open(std::string);
    void close();

    int insertRecord();
    int deleteRecord();
    int getNumUserRecords();
};

Here is how I am trying to use the callback (callbackSel), from within getNumUserRecords:

int DBAdapter::getUserRecords(std::string name)
{
    std::string sql = "SELECT" + name + " from USERS";
    char* ErrMsg;
    char* data;

    int retval = sqlite3_exec(db,sql.c_str(),this->callbackSel,data,&ErrMsg);
    return retval;
}

The error message I am getting is:

 error: ‘int (* DBAdapter::callbackSel)(void*, int, char**, char**)’ is not a static member of ‘class DBAdapter’

My problem is, if I make this a static function, I won't be able to have access to my vector, records, right? Is there any way around this?

回答1:

Is there any way around this?

I don't know for sqlite API specifically, but usually c-style callbacks support to have user data passed from a void* pointer (I'd guess the 1st parameter of that signature you mention). What one typically does is:

  1. Declare a static class function to specify as callback function pointer
  2. Implement that function to cast the passed user data pointer to a pointer to your class instance and call a member function
  3. Have a member function defined in the class that provides the implementation you want
  4. Pass a pointer to your handling class instance, when you're going to register the static member function pointer with the C API

I hope this points out the right direction.