[gelöst] Mal wieder MySQL (windows / mingw)

Alles rund um die Programmierung mit Qt
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

[gelöst] Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Hallo,

ich traue mich nach all den gefundenen und durchgearbeiteten Anleitungen und Beiträgen fast nicht mehr zu fragen, aber ich bekomme die MySQL-Plugin-Erstellung immer noch nicht hin (WinXP SP3 / Qt 4.8.0 / MySQL 5.5.12).

Hier ein Auszug an Links :-):
http://ieatbinary.com/2011/07/11/how-to ... r-windows/
http://doc.qt.nokia.com/4.7-snapshot/sq ... tml#qmysql
http://lists.trolltech.com/qt-interest/ ... 593-0.html
...

das Reimp / dlltool funktioniert, ich habe eine Datei "libmysql.a" erhalten
das anschließende qmake funktioniert auch noch(siehe Output), aber beim finalen mingw32-make bringt er folgenden Output:

Code: Alles auswählen

C:\Installation\QtSDK\QtSources\4.8.0\src\plugins\sqldrivers\mysql>qmake "INCLUD
EPATH+=%mysql%/include" "LIBS+=%mysql%/lib/libmysql.lib" -o Makefile mysql.pro

C:\Installation\QtSDK\QtSources\4.8.0\src\plugins\sqldrivers\mysql>mingw32-make
mingw32-make -f Makefile.Debug all
mingw32-make[1]: Entering directory `C:/Installation/QtSDK/QtSources/4.8.0/src/p
lugins/sqldrivers/mysql'
g++ -mthreads -shared -Wl,--out-implib,c:\Installation\QtSDK\QtSources\4.8.0\plu
gins\sqldrivers\libqsqlmysqld4.a -o ..\..\..\..\plugins\sqldrivers\qsqlmysqld4.d
ll tmp/obj/debug_shared/main.o tmp/obj/debug_shared/qsql_mysql.o tmp/obj/debug_s
hared/moc_qsql_mysql.o  -L"c:\Installation\QtSDK\QtSources\4.8.0\lib" -L"c:\Inst
allation\QtSDK\QtSources\4.8.0\lib" tmp\obj\debug_shared\qsqlmysqld_resource_res
.o -lmysql c:/Installation/MySQL/lib/libmysql.lib -lQtSqld4 -lQtCored4
c:/installation/qtsdk/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../../mingw32/bin
/ld.exe: cannot find -lmysql
collect2: ld returned 1 exit status
mingw32-make[1]: *** [..\..\..\..\plugins\sqldrivers\qsqlmysqld4.dll] Error 1
mingw32-make[1]: Leaving directory `C:/Installation/QtSDK/QtSources/4.8.0/src/pl
ugins/sqldrivers/mysql'
mingw32-make: *** [debug-all] Error 2
"cannot find -lmysql"? Die bei Google gefundenen Foreneinträge zu dem Thema helfen mir leider nicht weiter. Bei diversen andere Anleitungen wird vor dem qmake noch bspw. ein "configure.exe -debug-and-release -plugin-sql-mysql" ausgeführt. Ist dieses configure notwendig bzw. was macht das genau? (die Anleitungen machen leider keine Aussagen, warum man etwas machen soll, was zu Verständnisproblemen führt) Beim Versuch configure zu benutezn bekomme ich auch nur Fehlermeldungen. Viele Anleitungen beziehen sich auch auf ältere Qt-Versionen / MySQL-Versionen, so das die entsprechenden Strukturen (insbesondere im QtSDK-Ordner) anders aussehen.

Ihr könnt mich doch bestimmt auf die richtige Spur bringen...

bis dann,
dd0815
Zuletzt geändert von dd0815 am 10. Juli 2012 14:29, insgesamt 1-mal geändert.
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Hallo nochmal,

nachdem ich grade zufällig mitbekommen habe, dass ich auf eine MySQL-Datenbank auch mit dem ODBC-Treiber zugreifen kann (und mir so die mühselige Erstellung des MySQL-Treibers erspare), wollte ich das mal ausprobieren (siehe folgenden Testcode):

Code: Alles auswählen

database::database()
{
//    db = new QSqlDatabase();
//    db->addDatabase("QMYSQL");

    db = new QSqlDatabase();
    db->addDatabase("QODBC");

}

void database::open()
{
    bool ok;
    if (!db->isOpen())
    {
        db->setHostName("localhost");
        db->setDatabaseName("ferag3");
        //db->setDatabaseName("Driver={MySQL ODBC 5.5 Driver};DATABASE=ferag3;");
        //db->setPort(3306);
        db->setUserName("root");
        db->setPassword("");
        ok = db->open();

        QString output = QString("Datenbank öffnen (%1)")
                         .arg(ok);
        emit log(output);
    }
    else
    {
        db->close();

        QString output = QString("Datenbank geschlossen");
        emit log(output);
    }
}
Einzig und allein die Verbindung kommt nicht zustande (ok ist false). Ich habe lokal XAMPP 1.7.7 installiert und unter localhost kann man sich auch alles schön im Browser anschauen. Im phpmyadmin habe ich auch die Datenbank "ferag3" erzeugt, auf die ich nun zugreifen möchte. Fehlermeldungen im Output meiner Anwendung / der QtSDK kommen auch keine.

Wie kann ich herausfinden, warum das Öffnen nicht funktioniert?

bis dann,
dd0815...
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Hallo Fiend,

danke für die schnelle Antwort, aber das ist es leider nicht. Die Funktion "open" wird durch einen QPropertyBrowser aufgerufen, so dass die Funktion auch die Datenbank schliesst wenn diese offen ist. Andersrum wird die Datenbank nur geöffnet, wenn sie noch nicht offen ist und genau das testet die erste if-Bedingung...

bis dann,
dd0815
Markus
Beiträge: 105
Registriert: 31. Januar 2005 16:21

Re: Mal wieder MySQL (windows / mingw)

Beitrag von Markus »

Hallo!

Ich habe mir mal das kleine HowTo als Gedankenstütze geschrieben. Vielleicht hilft es Dir.

HowTo: SQLDrivers-Plugin "MySQL" mittels MinGW erstellen
Voraussetzung:
Über das MySQL-Server-Setup nur die "Development Components -> Client C API library" installieren.
Wichtig: Keine Leerzeichen im Installationspfad!

Beispiel-Verzeichnisse für dieses HowTo:
MySQL-API-Library: C:\MySQL\Server\
Qt: C:\DevTools\QtSDK

Schritt #1:
Qt-Eingabeaufforderung (CMD) starten. Normalerweise existiert ein Eintrag im Startmenü unter "Qt SDK".

Schritt #2:
In das Source-Verzeichnis vom MySQL-Plugin wechseln.
C:\DevTools\QtSDK\QtSources\4.8.1\src\plugins\sqldrivers\mysql

Schritt #3:
Mit Hilfe von QMake die Makefiles des Projektes erstellen.
Befehl: qmake "INCLUDEPATH+=C:/MySQL/Server/include" "LIBS+=C:/MySQL/Server/lib/libmysql.lib" mysql.pro

Schritt #4:
Das MySQL-Plugin kompilieren. (Evtl. den gesamten Pfad zum Programm verwenden)
Befehl für die Release-Version: C:\DevTools\QtSDK\mingw\bin\mingw32-make.exe -f Makefile.Release
Befehl für die Debug-Version: C:\DevTools\QtSDK\mingw\bin\mingw32-make.exe -f Makefile.Debug

Schritt #5:
Die Datei "qsqlmysql4.dll" aus dem release-Verzeichnis und wenn kompiliert, die Datei "qsqlmysqld4.dll" aus dem Debug-Verzeichnis in das Standard-Plugin-Verzeichnis C:\DevTools\QtSDK\Desktop\Qt\4.8.1\mingw\plugins\sqldrivers kopieren.

Zusätzlich noch die "libmysql.dll" auf dem Verzeichnis C:\MySQL\Server\lib in das Verzeichnis C:\DevTools\QtSDK\Desktop\Qt\4.8.1\mingw\bin
kopieren, damit das Plugin erkannt wird und der MySQL-Client zur Verfügung steht.

Qt-Check: Mit dem Programmbefehl qDebug() << QSqlDatabase::drivers() sollte der Eintrag "QMYSQL" als Debug-Ausgabe angezeigt werden.
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Hallo Markus,

vielen Dank für Deine ausführliche Anleitung, nun bin ich etwas weitergekommen. Ich denke meine Qt-Installation war etwas unübersichtlich (unter Desktop 3 Qt Versionen, Quellen nur 4.8.0). Jetzt habe ich Deine Anleitung auf einem anderen Rechner mit den 4.8.1 Sourcen und dem neuesten MySql (5.5.23) noch einmal nachvollzogen. Und tatsächlich, ohne reimp/dlltools und ohne configure war es mir möglich, die beiden dlls zu erstellen (es gab nur leichte Pfadprobleme, also habe ich bei dem qmake-Befehl bei den Pfade zum MySQL Backslashes benutzt). Jetzt tauchen unter den Treibern auch "QMYSQL3" und "QMYSQL" auf (qDebug-Anzeige).

Mittlerweile habe ich auch mitbekommen, dass es die Funktion "lastError()" in der Klasse QSqlDatabase gibt. Diese sagt mir nun nach dem Versuch des Datenbank Öffnens "QSqlError(-1, "Driver not loaded", "Driver not loaded"). Offensichtlich hat es der Treiber immer noch nicht ganz geschafft. Ich bin im Debug-Modus und habe dort auch schon diverse Verzeichnisse (plugins / sqldrivers / mysql) angelegt und die qsqlmysqld4.dll reinkopiert (was wahrscheinlich nicht die Ursache ist :-) )

bis dann,
dd0815...

P.S. Ist das jetzt tragisch, dass das xampp die mysql Version 5.5.16 benutzt, aber die benutzten Sourcen die Version 5.5.23 haben?
Markus
Beiträge: 105
Registriert: 31. Januar 2005 16:21

Re: Mal wieder MySQL (windows / mingw)

Beitrag von Markus »

dd0815 hat geschrieben:Diese sagt mir nun nach dem Versuch des Datenbank Öffnens "QSqlError(-1, "Driver not loaded", "Driver not loaded"). Offensichtlich hat es der Treiber immer noch nicht ganz geschafft. Ich bin im Debug-Modus und habe dort auch schon diverse Verzeichnisse (plugins / sqldrivers / mysql) angelegt und die qsqlmysqld4.dll reinkopiert (was wahrscheinlich nicht die Ursache ist :-) )
Wenn Du Deine Applikation im QtCreator (oder VisualStudio) startest, brauchst Du keine Verzeichnisse anlegen. Dann sollten alle Pfade gesetzt sein. Funktioniert das?

Läuft die Applikation auf dem Ziel-/Clientrechner, dann muss es im Applikationsverzeichnis das Unterverzeichnis "sqldrivers" geben, in dem die Datei "qsqlmysql4.dll" liegt (Release-Version, mit "d" am Ende für Debug-Version). Im Applikationsverzeichnis muss die Datei "libmySQL.dll" liegen.
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Hallo Markus,

ich benutze den QtCreator und habe bisher die Applikation nur von dort gestartet. Funktioniert also nicht.

In der Debugausgabe steht immer:

Code: Alles auswählen

Starte C:\Daten\03_Projekte\000_Datenbank\Applikation\Datenbank-build-desktop\debug\Datenbank.exe...("QSQLITE", "QMYSQL3", "QMYSQL", "QODBC3", "QODBC") 
QSqlError(-1, "Driver not loaded", "Driver not loaded") 
QSqlQuery::exec: database not open
die Bibliotheken libmysql.dll sowie die qsqlmysql(d)4.dll habe ich neben den von Dir genannten QtSDK-Verzeichnissen auch noch in die Projekt Debug / Realease-Verzeichnisse kopiert. Dann habe ich testweise auch noch einen "Deploy"-Ordner mit der Release-Version gemacht und sämtliche vom Programm geforderten dlls (QtCore4.dll, Gui4, SQL4, mingwm10.dll, libmysql.dll, libgcc_s_dw2-1.dll) sowie im Verzeichnis sqldrivers die Datei qsqlmysql4.dll kopiert... Nichts hat funktioniert.

Hier mal mein Projektfile:

Code: Alles auswählen

QT += network \
      core \
      gui \
      sql \

HEADERS += src/mainWindow.h \
    src/datei.h \
    src/database.h

SOURCES += src/main.cpp \
    src/mainWindow.cpp \
    src/datei.cpp \
    src/database.cpp

include(./../Addons/qtpropertybrowser-2.5_1-opensource/src/qtpropertybrowser.pri)

#QTPLUGIN += QMYSQL

#RC_FILE = src/res.rc
Die Zeile mit dem QtPlugin ist auskommentiert, wenn ich sie aktiviere, kommt beim Kompilieren folgendes:

Code: Alles auswählen

c:/installation/qtsdk/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../../mingw32/bin/ld.exe: cannot find -lqmysqld
collect2: ld returned 1 exit status
Benötige ich diese Zeile überhaupt? Habe ich nach Deiner Anleitung ein vollwertiges Plugin erstellt, oder brauche ich doch das ominöse configure, um meiner Entwicklungsumgebung das Plugin bekannt zu machen, oder reicht es wenn die Treiber auftauchen?

bis dann,
dd0815...
Markus
Beiträge: 105
Registriert: 31. Januar 2005 16:21

Re: Mal wieder MySQL (windows / mingw)

Beitrag von Markus »

dd0815 hat geschrieben:

Code: Alles auswählen

Starte C:\Daten\03_Projekte\000_Datenbank\Applikation\Datenbank-build-desktop\debug\Datenbank.exe...("QSQLITE", "QMYSQL3", "QMYSQL", "QODBC3", "QODBC") 
QSqlError(-1, "Driver not loaded", "Driver not loaded") 
QSqlQuery::exec: database not open
Kannst Du den Quellcode posten, der die obigen Debug-Messages erzeugt? Weil die Datenbank-Plugins für MySQL werden erkannt bzw. sind vorhanden. Nach meiner Erfahrung kann der Fehler "Driver not loaded" mehr bedeuten als das reine Fehlen des Treibers.
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Code: Alles auswählen

void database::open()
{
    bool ok;
    QString output;

    if (!db->isOpen())
    {
        db->setHostName("localhost");
        //db->setDatabaseName("cdcol");
        db->setDatabaseName("ferag3");
        //db->setConnectOptions();
        //db->setDatabaseName("DRIVER={MySQL ODBC 5.1 Driver};SERVER=LOCALHOST\\mysql;DATABASE=ferag3;Trusted_Connection=Yes;");
        //db->setPort(3306);
        db->setUserName("root");
        db->setPassword("");
        ok = db->open();

        if (ok)
        {
            output = QString("Datenbank geöffnet");
        }
        else
        {
            QSqlError err = db->lastError();
            output = QString("Fehler Datenbank öffnen (%1)")
                    .arg(err.driverText());
            qDebug() << db->lastError();
        }
        emit log(output);

        QSqlQuery query;
        query.exec("SELECT * FROM projekte");
        while (query.next())
        {
           int idx = query.value(0).toInt();
           QString prj = query.value(1).toString();
           qDebug() << idx << ": " << prj;
        }

    }
    else
    {
        db->close();

        QString output = QString("Datenbank geschlossen");
        emit log(output);
    }

}
Markus
Beiträge: 105
Registriert: 31. Januar 2005 16:21

Re: Mal wieder MySQL (windows / mingw)

Beitrag von Markus »

Mir fällt spontan eine Sache ein: Setze mal zusätzlich den MySQL-Port für Dein DB-Objekt, weil ich mir nicht sicher bin, ob das default-mäßig gemacht wird.

Code: Alles auswählen

db->setPort( 3306 );
Und sonst poste nochmal das Erzeugen der Variable "db".
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Hallo Markus,

alles was im Beispielcode zu sehen ist, habe ich ausprobiert, auch das Port setzen.

Hier meine gesamte Klasse "database":

Code: Alles auswählen

#ifndef DATABASE_H
#define DATABASE_H

#include <QtCore>
#include <QDialog>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
//#include <QODBCDriver>

class database : public QDialog
{
    Q_OBJECT

public:
    database();
    void open();
    void close();

signals:
    void log( const QString& );

private:
    QSqlDatabase *db;

};

#endif // DATABASE_H

Code: Alles auswählen

#include "database.h"

database::database()
{
    db = new QSqlDatabase();
    db->addDatabase("QMYSQL");

    qDebug() << QSqlDatabase::drivers();
//    db = new QSqlDatabase();
//    db->addDatabase("QODBC");

}

void database::open()
{
    bool ok;
    QString output;

    if (!db->isOpen())
    {
        db->setHostName("localhost");
        //db->setDatabaseName("cdcol");
        db->setDatabaseName("ferag3");
        //db->setConnectOptions();
        //db->setDatabaseName("DRIVER={MySQL ODBC 5.1 Driver};SERVER=LOCALHOST\\mysql;DATABASE=ferag3;Trusted_Connection=Yes;");
        //db->setPort(3306);
        db->setUserName("root");
        db->setPassword("");
        ok = db->open();

        if (ok)
        {
            output = QString("Datenbank geöffnet");
        }
        else
        {
            QSqlError err = db->lastError();
            output = QString("Fehler Datenbank öffnen (%1)")
                    .arg(err.driverText());
            qDebug() << db->lastError();
        }
        emit log(output);

        QSqlQuery query;
        query.exec("SELECT * FROM projekte");
        while (query.next())
        {
           int idx = query.value(0).toInt();
           QString prj = query.value(1).toString();
           qDebug() << idx << ": " << prj;
        }

    }
    else
    {
        db->close();

        QString output = QString("Datenbank geschlossen");
        emit log(output);
    }

}

void database::close()
{

}
diese im Konstruktor des MainWindow erzeugt:

Code: Alles auswählen

    datab = new database();

    // Logging aus db
    connect(datab, SIGNAL(log(const QString&)),
            this, SLOT(writeLog(const QString&)));
und hier wird das open aufgerufen (wenn im PropertyBrowser das Feld verbinden aktiviert wird):

Code: Alles auswählen

void mainWindow::propChanged(QtProperty *property, const QVariant &value)
{
    bool ok;

    if (property->propertyName() == tr("Verbinden"))
    {
        datab->open();
        return;
    }

}
Ich glaube nicht das es am Code liegt. Habe das Öffnen auch mal aus der Klasse rausgenommen und direkt ins mainWindow gemacht. Auch nichts...

Du meinst, das mit den Plugins ist alles i.O., wenn diese mit QSqlDatabase::drivers() erkannt werden?

Noch eine Frage: wenn das alles mal gehen sollte, woher weiß das QSqlQuery, auf welche Datenbank sich die Anfrage bezieht? (es können doch mehrere Datenbanken gleichzeitig geöffnet sein, oder?)

bis dann,
dd0815...

P.S der Dependency Walker meldet nur das Fehlern von IESHIMS.DLL und WER.DLL in der QtCore4.dll
Markus
Beiträge: 105
Registriert: 31. Januar 2005 16:21

Re: Mal wieder MySQL (windows / mingw)

Beitrag von Markus »

Puuh.... Echt kniffelig...

Also ich erzeuge meine DB-Objekte wie folgt:

Code: Alles auswählen

QSqlDatabase sqlDB_Default = QSqlDatabase::addDatabase("QMYSQL");
Aber das sollte keinen Unterschied machen (glaube ich).

Zu der Frage: Bei der Methode addDatabase() kannst Du einen ConnectionName angeben, um die Datenbanken zu unterscheiden. Bei QSqlQuery kannst Du dann das QSqlDatabase-Objekt als Paramter angeben, um so zu entscheiden, über welche DB Du arbeiten willst.

Als Test würde ich noch schauen, ob Du vielleicht die Pfade zu den MySQL-Dateien (libs/dll) in die Umgebungsvariable PATH aufnimmst.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: Mal wieder MySQL (windows / mingw)

Beitrag von franzf »

Code: Alles auswählen

database::database()
{
    db = new QSqlDatabase();
    db->addDatabase("QMYSQL");
und WIE das einen Unterschied macht! addDatabase ist ne statische Methode. statische Methoden kann man auch über eine Instanz aufrufen, ja, sie haben aber eben KEINEN Einfluss auf das Objekt.
db ist in deinem Kontext ein unintialisiertes, dysfunktionales Objekt.

Außerdem solltest du dich fragen, ob ein Zeiger hier angebracht ist (QSqlDatabase-Objekte sind kopierbar, und so sollten sie auch verwendet werden).
Markus
Beiträge: 105
Registriert: 31. Januar 2005 16:21

Re: Mal wieder MySQL (windows / mingw)

Beitrag von Markus »

franzf hat geschrieben:und WIE das einen Unterschied macht! addDatabase ist ne statische Methode. statische Methoden kann man auch über eine Instanz aufrufen, ja, sie haben aber eben KEINEN Einfluss auf das Objekt.
Ich war mir nicht 100% sicher. Wieder etwas gelernt!
dd0815
Beiträge: 37
Registriert: 8. Juni 2010 16:28

Re: Mal wieder MySQL (windows / mingw)

Beitrag von dd0815 »

Hallo Markus / franzf,

habe es auch grade herausgefunden, mit dem Beispielcode aus http://doc.qt.nokia.com/4.7-snapshot/sq ... cting.html funktionierts :

Code: Alles auswählen

    QString output;

    QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
         db.setHostName("localhost");
         db.setDatabaseName("ferag3");
         db.setUserName("root");
         db.setPassword("");

         if (db.open())
         {
             output = QString("Datenbank geöffnet");
             qDebug() << "habe geöffnet";
             QSqlQuery query;
             query.exec("SELECT * FROM projekte");
             while (query.next())
             {
                int idx = query.value(0).toInt();
                QString prj = query.value(1).toString();
                qDebug() << idx << ": " << prj;
             }

         }
         else
         {
             QSqlError err = db.lastError();
             output = QString("Fehler Datenbank öffnen (%1)")
                     .arg(err.driverText());
             qDebug() << db.lastError();
         }
         emit log(output);
Ich wollte einen Zeiger benutzen, weil ich mit mehreren Funktionen meiner Klasse "database" auf die Datenbank zugreifen wollte und den Datenbankzugriff in der gesamten Klasse zur Verfügung haben wollte. Klingt vielleicht nicht einleuchtend, gehört aber alles noch zum Trial&Error. In meiner Eigenschaft als nichtberuflicher PC-Programmierer weiß ich natürlich, dass ich noch etwas dazulernen muß, um die 3 Zeilen von franzf zu verstehen :-)

Vielen Dank für Eure Hilfe...

bis dann,
dd0815...
Antworten