SQLite3 Callbackfunktion wird nicht aufgerufen



  • Hi Leute,
    Ich habe mir gerade einen anderen Thread gelesen und dabei ist mir aufgefallen, dass ich das ganze sch**** mache(ähm ich meine umschtändlich 😉 )... Wird jetzt auch umgeschrieben werden, aber trotzdem interessiert mich, warum das nicht klappt... Hier die Klasse SQLite3Database:

    class SQLite3Database
    {
    public:
      SQLite3Database(const char* dbPath)
        {
        loadDatabase(dbPath);
        }
      ~SQLite3Database()
        {
        closeDatabase();
        }
      bool isOpen()
        {
        return databaseOpened;
        }
      bool execute(char *query, int *numOfResults, char ***results, char ***columnNames)
        {
        char* pointersChar = "";
        printf(pointersChar, "%i, %i, %i", numOfResults, results, columnNames);
        wprintf(L"Execute:\n  %i\n  %i\n  %i\n", numOfResults, results, columnNames);
        void* pointersVoid = (void*)pointersChar;
    
        int rv;
        char *errMsg = 0;
    
        rv = sqlite3_exec(db, query, callback, pointersVoid, &errMsg);
    
        if(rv != SQLITE_OK)
          {
          return false;
          }
        else
          {
          return true;
          }
        }
      bool execute(char *query)
        {
        int *numOfResults = new int;
        char ***results = new char**;
        char ***columnNames = new char**;
    
        bool result = execute(query, numOfResults, results, columnNames);
    
        delete numOfResults;
        delete results;
        delete columnNames;
    
        return result;
        }
    private:
      sqlite3 *db;
      bool databaseOpened;
    
      void loadDatabase(const char* dbPath)
        {
        int rv;
        rv = sqlite3_open(dbPath, &db);
        if(rv == 1)
          {
          databaseOpened = false;
          }
        else
          {
          databaseOpened = true;
          }
        }
      void closeDatabase()
        {
        if(databaseOpened)
          {
          sqlite3_close(db);
          }
        }
      static int callback(void *pointersVoid, int numOfResults, char **results, char **columnNames)
        {
        const char *pointersChar = (const char*)pointersVoid;
    
        int addresses[3];
    
        int *numOfResultsP;
        char ***resultsP;
        char ***columnNamesP;
        scanf(pointersChar, "%i, %i, %i", addresses[0], addresses[1], addresses[2]);
    
        wprintf(L"Callback:\n  %i\n  %i\n  %i\n\n", addresses[0], addresses[1], addresses[2]);
    
        *numOfResultsP = numOfResults;
        *resultsP = results;
        *columnNamesP = columnNames;
    
        return 0;
        }
    };
    

    und hier der Aufruf:

    char* query = "SELECT * from TEXTURES";
    
    int numOfResults = 0;
    char **results;
    char **columnNames;
    std::cout << "Cout: " << &numOfResults << std::endl;
    wprintf(L"Original:\n  %i\n  %i\n  %i\n", &numOfResults, &results, &columnNames);
    
    if(!Project->execute(query, &numOfResults, &results, &columnNames))
      {
      wprintf(L"Reading TEXTURES table failed\n");
      system("pause");
      }
    else
      {
      wprintf(L"Reading TEXTURES table successful\n");
      }
    
    wprintf(L"Results: %i\n", numOfResults);
    for(int i = 0; i < numOfResults; i++)
       {
       wprintf(L"%S = %S\n", *columnNames[i], *results[i]);
       }
    wprintf(L"\n");
    system("pause");
    

    Die Ausgabe lautet:

    Cout: 0x28feb4
    Original:
      2686644
      2686640
      2686636
    Execute:
      2686644
      2686640
      2686636
    Reading TEXTURES table successful
    Results: 0
    

    ->Die Callbackfunktion wird nicht aufgerufen... Wieso?!?
    Danke schon mal im Voraus
    MfG
    DragonRaider



  • DragonRaider schrieb:

    Die Ausgabe lautet:

    Cout: 0x28feb4
    Original:
      2686644
      2686640
      2686636
    Execute:
      2686644
      2686640
      2686636
    Reading TEXTURES table successful
    Results: 0
    

    Huh?
    Bei der Ausgabe muss Dir doch selber auffallen, dass Du erhebliche Wissenslücken hast..?!

    Du verhedderst Dich irgendwo im Dickicht von Sternchen, Casts, C und C++.

    Lern die Grundlagen.



  • Hi Furble,
    Willst du mir damit sagen, dass ich mir da die Adressen ausgeben lasse? Wenn ja: Das war auch der Sinn und Zweck der Sache 😉 . Damit wollte ich überprüfen, ob die Adressen der chars in meiner Callbackfunktion richtig ankommen, nachdem ich sie mit printf zusammengesetzt, von nem char* zu nem void* und zurück gecastet habe und sie anschließend mit scanf wieder auseinander gepflückt hab...
    MfG
    DragonRaider



  • DragonRaider schrieb:

    Hi Furble,
    Willst du mir damit sagen, dass ich mir da die Adressen ausgeben lasse? Wenn ja: Das war auch der Sinn und Zweck der Sache ;

    Das habe ich nicht geahnt.
    Trotzdem bleibt da ein heilloses Gewirr von Zeigern und Casts.
    Ich weiss, dass es Dir wahrscheinlich mehr hülfe, wenn ich auf Deinen Code einginge, aber ich habe schlicht keine Lust einen Knoten in mein Hirn zu knüpfen.

    Ich habe mir die API gerade angeschaut und bin jetzt bei sowas gelandet:

    #include <iostream>
    #include <string>
    
    #include <sqlite3.h>
    
    class sqlite3_db{
      sqlite3* db;
    public:
      sqlite3_db(const char* path){
        sqlite3_open(path, &db);
      }
      ~sqlite3_db() { sqlite3_close(db); }
      sqlite3_db(const sqlite3_db&) = delete;
      sqlite3_db(sqlite3_db&&) = delete;
      sqlite3_db& operator=(const sqlite3_db&) = delete;
      sqlite3_db& operator=(const sqlite3_db&&) = delete;
      void execute(const std::string& stmt){
        char* errmsg;
        void* msg=const_cast<void*>(static_cast<const void*>("Hallo Welt!"));
        int e = sqlite3_exec(db, stmt.c_str(), callback,  msg, &errmsg);
        if( e!= SQLITE_OK){
          std::cerr << "Error in sqlite3_db::execute(): " << errmsg << '\n';
          sqlite3_free(errmsg);
        }
      }
      static int callback(void* msg, int argc, char** cols, char** col_names){
        std::cout << static_cast<const char*>(msg) << '\n';
        while(argc--)
          std::cout << *col_names++ << ": " << *cols++ << '\n';
        return 0;
      }
    };
    
    int main(){
      sqlite3_db db("test.sqlite");
      db.execute("select * from textures;");
    }
    

    Ich schlage vor, Du vereinfachst Deinen Code erheblich.
    Eventuell kannst Du mich ja auch erleuchten, was es mit den Zeigern, Zeigern auf Zeiger und Zeigern auf Zeiger auf Zeiger so auf sich hat!?



  • Oh hübsch!
    Ich habe gerade noch den speziellen Namen :memory: entdeckt...

    int main(){
      std::string create = R"(CREATE TABLE "textures" ("name" varchar[64], "path" varchar[64]);
                              INSERT INTO textures VALUES("texture1", "texture1_path");
                              INSERT INTO textures VALUES("texture2", "texture2_path");
                              INSERT INTO textures VALUES("texture3", "texture3_path");
                           )";
      std::string show = "select * from textures;";
      sqlite3_db db(":memory:");
      db.execute(create);
      db.execute(show);
    }
    


  • Zwei klitzekleine Sachen:
    1. Seid ihr nicht eigentlich dagegen, dass man fertigen Code postet, anstatt es einfach zu erklären?
    2. Wie soll ich jetzt an die Daten aus der DB kommen?
    Trotzdem danke 🙂
    MfG
    DragonRaider



  • DragonRaider schrieb:

    1. Seid ihr nicht eigentlich dagegen, dass man fertigen Code postet, anstatt es einfach zu erklären?

    Ich kann Dir Deinen Code nicht erklären. Ich verstehe ihn nicht - und ich habe auch keine Zeit/Lust mich einzuarbeiten.
    Das sind 120 Zeilen und an jeder kann man wahrscheinlich was aussetzen.

    const char *pointersChar = (const char*)pointersVoid;
    
        int addresses[3];
    
        int *numOfResultsP;
        char ***resultsP;
        char ***columnNamesP;
        scanf(pointersChar, "%i, %i, %i", addresses[0], addresses[1], addresses[2]);
    

    Was soll das werden? in Zeile 6 und 7 kommen mir die Tränen. In Zeile 8 dem Compiler!

    Oder das:

    int *numOfResults = new int;
        char ***results = new char**;
        char ***columnNames = new char**;
    
        bool result = execute(query, numOfResults, results, columnNames);
    
        delete numOfResults;
        delete results;
        delete columnNames;
    

    Du bist völlig verwirrt durch die Zeiger des C-APIs von sqlite und schmeisst Sternchen und casts in den Code, damit es kompiliert.
    Da ist nichts zu erklären, das ist Fubar!

    Deswegen - und das ist durchaus üblich - habe ich Dir ein Minimalbeispiel gebaut. Fast ohne Sternchen und Casts, ohne new und delete, damit Du Dir vielleicht was abgucken kannst.

    DragonRaider schrieb:

    2. Wie soll ich jetzt an die Daten aus der DB kommen?

    Nun: Du bastelst Dir einen Callback, der irgendwas macht. Z.B. könntest Du Die Datenbankeinträge in einen vector blasen

    #include <iostream>
    #include <string>
    #include <vector>
    
    #include <sqlite3.h>
    
    struct texture{
      std::string name;
      std::string path;
    };
    
    std::ostream& operator<<(std::ostream& out, const texture& t){
      return out << '(' << t.name << " @ " << t.path << ')';
    }
    
    class sqlite3_db{
      sqlite3* db;
    public:
      typedef std::vector<texture> t_vec;
      sqlite3_db(const char* path){
        sqlite3_open(path, &db);
      }
      ~sqlite3_db() { sqlite3_close(db); }
      sqlite3_db(const sqlite3_db&) = delete;
      sqlite3_db(sqlite3_db&&) = delete;
      sqlite3_db& operator=(const sqlite3_db&) = delete;
      sqlite3_db& operator=(const sqlite3_db&&) = delete;
    
      void execute(const std::string& stmt){
        char* errmsg;
        int e = sqlite3_exec(db, stmt.c_str(), nullptr, nullptr, &errmsg);
        if( e!= SQLITE_OK){
          std::cerr << "Error in sqlite3_db::execute(): " << errmsg << '\n';
          sqlite3_free(errmsg);
        }
      }
    
      t_vec give_textures(){
        // mein callback (gegen die Langeweile mal ein Lambda)
        auto filler = [](void* vec, int argc, char** cols, char** col_names) -> int{
          t_vec* target = static_cast<t_vec*>(vec);
          target->push_back({cols[0], cols[1]});
          return 0;
        };
        char*errmsg;
        t_vec ret;
        if(sqlite3_exec(db, "SELECT * FROM textures;", filler, (void*)&ret, &errmsg) != SQLITE_OK){
          std::cerr << "Cannot give textures. Error is: " << errmsg << '\n';
          sqlite3_free(errmsg);
        }
        return ret;
      }
    };
    
    int main(){
      std::string create =
        "CREATE TABLE textures (name TEXT, path TEXT);"
        "INSERT INTO textures VALUES('texture1', 'texture1_path');"
        "INSERT INTO textures VALUES('texture2', 'texture2_path');"
        "INSERT INTO textures VALUES('texture3', 'texture3_path');";
      sqlite3_db db(":memory:");
      db.execute(create);
      auto vec = db.give_textures();
      for(const auto& t : vec)
        std::cout << t << '\n';
    }
    

    Gutes Gelingen! 🙂


Log in to reply