Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL- und MariaDB-Bibliotheken in C++ mit cmake, mingw

Sowohl MySQL als auch MariaDB (die das gleiche Erbe teilen ). ) sind dazu bestimmt, nur mit Visual Studio unter Windows kompiliert und verwendet zu werden . Sie werden viele frühere Fragen zu StackOverflow dazu finden. Das Problem bei ihnen ist, dass sie viele Strukturen definieren, die bereits in der Standardbibliothek definiert sind, und dann auch auf die Standardbibliothek verlinken.

Ich empfehle Ihnen, entweder zu Visual Studio oder zu einem Linux-System zu wechseln . Wenn Sie GCC unter Windows verwenden müssen, suchen Sie nach einem anderen Connector. Diese Probleme werden nicht einfach gelöst werden. In diesem Fall sind die Lösungen wahrscheinlich nicht portabel und funktionieren möglicherweise nicht mit zukünftigen Versionen der beiden Konnektoren. Sie können sich die Alternativen SQLite ansehen und SQLAPI++ .

Erstes Problem:Ganzzahlen mit fester Breite

Das erste Problem, das Sie erwähnen, hängt tatsächlich mit den Ganzzahltypen mit fester Breite zusammen und 32-Bit-Betriebssysteme, die in den Header-Dateien definiert sind. Es gibt die traditionellen Integer-Typen wie char , short , int , long und long long aber zusätzlich die oben erwähnten Ganzzahlen mit fester Breite.

Der MySql Connector definiert den int32_t Datentyp in config.h und auch die Standard-C++-Bibliothek definiert sie:MySql definiert den int32_t mit dem Compiler-Datentyp __int32

typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;

was sich überraschenderweise als long int herausstellt Datentypen

typedef long int int32_t;
typedef long unsigned int uint32_t;

während die Standardbibliothek sie als reguläre int definiert

typedef int int32_t;
typedef unsigned int uint32_t;

long ganzzahlige Datentypen sind garantiert mindestens 32-Bit :Auf einer 32-Bit-Architektur ein long int ist 32-Bit (genau wie ein int ), während sie für 64-Bit unterschiedliche Längen haben - ein long int ist 64-Bit und ein int ist nur 32-Bit (siehe ). hier ). Das bedeutet eigentlich, dass diese Definitionen für ein 32-Bit-System identisch sein sollten, aber der Compiler denkt, dass sie widersprüchlich sind.

Der MySql-Header ist von verschiedenen Definitionen umschlossen (ich habe ihnen eine Erklärung beigefügt, damit Sie verstehen können, warum die unten angegebenen Lösungsvorschläge tatsächlich funktionieren), die entscheiden, ob die entsprechenden Datentypen definiert werden sollen oder nicht

// Only define for 32-bit compilation
#if defined(_WIN32)
// Don't define if this custom flag is activated
#ifndef CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES
// Do not define for Visual Studio 2010 and later (but use C++ standard library instead)
#if _MSC_VER >= 1600
#include <stdint.h>
#else
// Only define if HAVE_MS_INT32 (another custom flag) is set to true (1)
#ifdef HAVE_MS_INT32
typedef __int32 int32_t;
#endif
// Some more data type defines...
#endif
#endif
#endif

Lösungen

Basierend auf der oben angegebenen Struktur der Header-Datei gibt es dafür einige Lösungen. Einige sind möglicherweise lebensfähiger, andere weniger.

  • Natürlich könnten Sie keine Typdefinitionen in cstdint einfügen und stdint.h und leben Sie mit den MySql-Definitionen. Dies wäre tatsächlich ziemlich einschränkend, da früher oder später wahrscheinlich ein anderer Standardbibliotheks-Header ihn enthalten wird, und es könnte dazu führen, dass Sie gezwungen werden, die Standardbibliothek überhaupt nicht zu verwenden, was sehr einschränkend sein könnte.

  • Sie könnten die 32-Bit-Build-Toolkette, die Sie verwenden, ganz aufgeben, zu einem **64-Bit-Compiler wechseln und für 64-Bit kompilieren . In diesem Fall sollte dies nicht als Header config.h geschehen in MySql ist wie oben angegeben nur für 32-Bit-Systeme enthalten! Wenn es keinen guten Grund gibt, dass Ihr Projekt 32-Bit sein sollte, würde ich das tatsächlich tun. Apropos Compiler:Sie scheinen GCC 6.3.0 zu verwenden, das bereits 2016 veröffentlicht wurde und eigentlich unterstützt C++17 nicht vollständig Sprachstandard Sie sagen ihm, dass es mit CMAKE_CXX_STANDARD 17 kompilieren soll in Ihrer CMake-Datei. Möglicherweise möchten Sie einen anderen neueren Compiler verwenden, falls Sie C++17-Funktionen ausgiebig nutzen möchten. Ansonsten ist C++14 auch nicht schlecht.

  • Sie könnten Visual Studio 2010 verwenden (Version 1600 ) oder später für die Kompilierung, da in diesem Fall der Header automatisch die Definitionen aus dem Standard enthält, anstatt eigene zu definieren.

  • Sie könnten das Präprozessor-Flag #define CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES definieren über Ihrem Code (oder innerhalb der IDE, die Sie für Ihr Projekt verwenden), als ob dieses Flag in der config.h gesetzt wäre Datei wird keine Datentypen definieren.

  • In ähnlicher Weise könnten Sie es auch lösen, indem Sie MYSQLC~1.0/include/jdbc/cppconn/config.h öffnen und ändern Sie die Präprozessoranweisungen von

    #define HAVE_MS_INT32  1
    #define HAVE_MS_UINT32 1
    

    zu

    #define HAVE_MS_INT32  0
    #define HAVE_MS_UINT32 0
    

    Dies deaktiviert die entsprechenden Definitionen für alle Programme, die Sie auch in Zukunft schreiben und die diesen Header enthalten.

Zweites Problem:Linken zu mit Visual Studio kompilierten Bibliotheken

Die zweite Fehlermeldung, die Sie erhalten, bezieht sich tatsächlich auf das Verknüpfen der Bibliothek. Unter Windows sind Bibliotheken, die mit unterschiedlichen Compilern kompiliert wurden, generell nicht kompatibel. Dies bedeutet, dass ein mit GCC kompiliertes Programm keine mit Visual Studio kompilierten Bibliotheken enthalten kann. In Ihrem Fall wurde die DLL mit Visual Studio kompiliert und daher schlägt die Verknüpfung mit Ihrem GCC-Programm fehl.

Wie auch hier erwähnt Sie können CMake zwingen, MinGW anstelle von Visual Studio mit cmake -G "MinGW Makefiles" zu verwenden aber ich habe es versucht und es funktioniert weder mit MariaDB noch mit MySQL.

Mit MSYS2 In MySQL erhalte ich einen kryptischen Fehler im Zusammenhang mit OpenSSL, während ich auf MariaDB nach offizieller Leitfaden und dann mit

cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -G "MinGW Makefiles" -DCONC_WITH_UNIT_TESTS=Off -DCONC_WITH_MSI=OFF -DWITH_SSL=SCHANNEL .
cmake --build . --config RelWithDebInfo

Ich muss ein paar manuelle Änderungen vornehmen, wie z. B. das Ändern von /src/CArrayImp.h und ändern Sie Zeile 59 in 63 von

#ifndef _WIN32
# define ZEROI64 0LL
#else
# define ZEROI64 0I64
#endif

zu

#define ZEROI64 0LL

als 0I64 wird nur von Visual Studio definiert. Außerdem muss die Template-Instanziierung in CArray.cpp entfernt werden aber ich ende immer noch mit einem The system cannot find the path specified. Fehlermeldung. Ebenso konnte ich es nicht in Cygwin kompilieren.

SQL C++ Connector-Alternativen

Ich habe keine Lösung für das letzte Problem, aber vielleicht möchten Sie sich nach Alternativen umsehen. Sie können SQLite herunterladen aus dem Quellcode und kompilieren Sie es. Gemäß der Installationsanleitung aus den Quellen es ist mit MinGW kompatibel, aber nur leichtgewichtig . So sollte die Shareware SQLAPI++ sein . Laut ihrer "Bestellseite" die Testversion für Windows ist voll funktionsfähig

Beide sollten MySql unterstützen:z.B. siehe hier .

tl;dr: Verwenden Sie die MySQL- und MariaDB-Konnektoren unter Windows nur in Visual Studio . Wenn Sie Visual Studio nicht verwenden können, werfen Sie einen Blick auf die alternativen C++-SQL-Konnektoren wie SQLite und SQLAPI++ stattdessen.