1

I'm writing program using sqlite. I've got class dataSend_task, that periodicaly select data from BD and send it to server.

In dataSend_task i've got method callback, that I want to sent as argument to sqlite3_exec.

I've got error:

error: cannot convert ‘std::function<int(void*, int, char**, char**)>’ to ‘int (*)(void*, int, char**, char**)’ for argument ‘3’ to ‘int sqlite3_exec(sqlite3*, const char*, int (*)(void*, int, char**, char**), void*, char**)’
         if (sqlite3_exec(this->db, this->SQL_SELECT_READINGS_QUERY, callback, 0, &err)) {

Source code part:

int dataSend_task::callback(void *NotUsed, int argc, char **argv, char **columnName){...}

void dataSend_task::sendData()
{
    using namespace std::placeholders;
    std::function<int(void *, int, char **, char **)> callback = 
         std::bind(&dataSend_task::callback, this, _1, _2, _3, _4);

    if (sqlite3_exec(this->db, this->SQL_SELECT_READINGS_QUERY, 
                      callback, 0, &err)) 
    { ... }
}

As I understand problem is in converting callback to type that sqlite_exec accepts. But I don't know how to fix it.

Barry
  • 286,269
  • 29
  • 621
  • 977
Dm3Ch
  • 621
  • 1
  • 10
  • 26
  • You can't use `std::function` or `std::bind` with C functions, as those a C++ concepts that aren't known by a pure C library. You might want to look into a C++ wrapper library instead. Or use standard non-member functions or static member functions, or non-capturing lambdas. – Some programmer dude Jul 16 '15 at 18:31
  • Your solution definitely does not work. And regardless, solutions don't belong in the question - they belong in an answer. – Barry Jul 16 '15 at 19:11
  • On my computer it compiles. Can you explain why it doesn't works? – Dm3Ch Jul 16 '15 at 20:24
  • @Dm3Ch Compiles != works. `target()` returns a pointer to the underlying function if you match the type correctly, otherwise it returns a null pointer. You're not matching the type correctly, so you would get back a null pointer, which then `sqlite3_exec` would attempt to call. – Barry Jul 17 '15 at 15:27
  • @Barry I think I corectly matching type. How can I correct this problem& – Dm3Ch Jul 17 '15 at 15:54
  • @Dm3Ch No you didn't. You're assign it to a `bind` expression, which has unspecified type. I don't know how to spell that, do you? Its type *certainly* isn't a function pointer, because it cannot be - it has members. – Barry Jul 17 '15 at 15:55

1 Answers1

5

You cannot convert a std::function to a function pointer. However, you can still accomplish what you want with a lambda. Thanks to some sorcery, a lambda with no capture can be converted to a function pointer (exactly what you need). Notice also that sqlite3_exec() accepts a void* for the 1st argument - so you can use that in your no-capture lambda to actually call your member function:

if (sqlite3_exec(this->db, this->SQL_SELECT_READINGS_QUERY, 
    +[](void* instance, int x, char** y, char** z) {
        return static_cast<dataSend_task*>(instance)->callback(x, y, z);
    },
    this,
    &err))
{
    /* whatever */
}
Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • I did it as you say but callback function didn't run anyway. But sqlite didn't give error. – Dm3Ch Jul 17 '15 at 15:43