Mysql
 sql >> Database >  >> RDS >> Mysql

Le librerie MySQL e MariaDB in C++ usando cmake, mingw

Entrambi i connettori MySQL e MariaDB (che condividono la stessa eredità ) sono destinati a essere compilati e utilizzati solo con Visual Studio su Windows . Troverai molte domande precedenti su StackOverflow al riguardo. Il problema è che definiscono molte strutture che sono già definite nella libreria standard e quindi si collegano anche alla libreria standard.

Ti suggerisco di passare a Visual Studio oa un sistema Linux . Se devi usare GCC in Windows, cerca un altro connettore. Questi problemi non saranno risolti facilmente. In tal caso, è improbabile che le soluzioni siano portatili e potrebbero non funzionare con le versioni future dei due connettori. Puoi dare un'occhiata alle alternative SQLite e SQLAPI++ .

Primo problema:numeri interi a larghezza fissa

Il primo problema che menzioni è in realtà correlato ai tipi interi a larghezza fissa e sistemi operativi a 32 bit definiti nei file di intestazione. Ci sono i tipi interi tradizionali come char , short , int , long e long long ma in aggiunta i suddetti interi a larghezza fissa.

Il connettore MySql definisce il int32_t tipo di dati in config.h e anche la libreria C++ standard li definisce:MySql definisce il int32_t con il tipo di dati del compilatore __int32

typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;

che sorprendentemente risulta essere il long int tipi di dati

typedef long int int32_t;
typedef long unsigned int uint32_t;

mentre la libreria standard li definisce come normali int

typedef int int32_t;
typedef unsigned int uint32_t;

long tipi di dati interi sono garantiti almeno a 32 bit :Su un'architettura a 32 bit un long int è a 32 bit (proprio come un int ) mentre per 64 bit hanno lunghezze diverse:un long int è a 64 bit e un int è solo a 32 bit (vedi qui ). Ciò significa che in realtà per un sistema a 32 bit queste definizioni dovrebbero essere identiche, ma il compilatore pensa che siano in conflitto.

L'intestazione di MySql è racchiusa da vari define (vi metto una spiegazione accanto a loro in modo da poter capire perché le soluzioni proposte fornite di seguito funzionano effettivamente) che decidono se i tipi di dati corrispondenti devono essere definiti o meno

// 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

Soluzioni

Sulla base della struttura del file di intestazione data sopra, ci sono un paio di soluzioni per questo. Alcuni potrebbero essere più praticabili mentre altri meno.

  • Chiaramente potresti non includere le definizioni di tipo in cstdint e stdint.h e vivi con le definizioni di MySql. Questo in realtà sarebbe piuttosto limitante poiché prima o poi probabilmente un'altra intestazione di libreria standard lo includerà e potrebbe costringerti a non utilizzare affatto la libreria standard, il che potrebbe essere molto limitante.

  • Potresti abbandonare del tutto la catena di strumenti di compilazione a 32 bit che stai utilizzando, passare a un **compilatore a 64 bit e compilare per 64 bit . In questo caso ciò non dovrebbe accadere come header config.h in MySql è incluso solo per i sistemi a 32 bit come indicato sopra! Se non c'è una buona ragione per cui il tuo progetto dovrebbe essere a 32 bit, è quello che farei effettivamente. Parlando del tuo compilatore:sembra che tu stia usando GCC 6.3.0 che è stato rilasciato nel 2016 e in realtà non supporta completamente il C++17 standard linguistico gli stai dicendo di compilare con CMAKE_CXX_STANDARD 17 nel tuo file CMake. Potresti voler utilizzare un altro compilatore più recente nel caso in cui desideri utilizzare ampiamente le funzionalità di C++ 17. Altrimenti anche C++14 non è male.

  • Puoi utilizzare Visual Studio 2010 (versione 1600 ) o successivo per la compilazione in quanto in questo caso l'intestazione includerà automaticamente le definizioni dello standard anziché definirne di proprie.

  • Potresti definire il flag del preprocessore #define CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES sopra il tuo codice (o dentro l'IDE che stai usando per il tuo progetto) come se questo flag fosse impostato su config.h il file non definirà alcun tipo di dati.

  • Allo stesso modo potresti anche risolverlo aprendo MYSQLC~1.0/include/jdbc/cppconn/config.h e modificare le direttive del pre-processore da

    #define HAVE_MS_INT32  1
    #define HAVE_MS_UINT32 1
    

    a

    #define HAVE_MS_INT32  0
    #define HAVE_MS_UINT32 0
    

    Questo disattiverà le definizioni corrispondenti per tutti i programmi che scriverai anche in futuro che includono questa intestazione.

Secondo problema:collegamento a librerie compilate con Visual Studio

Il secondo messaggio di errore che ricevi è in realtà correlato al collegamento della libreria. Su Windows le librerie compilate con diversi compilatori non sono generalmente compatibili. Ciò significa che un programma compilato con GCC non può includere librerie compilate con Visual Studio. Nel tuo caso la DLL è stata compilata con Visual Studio e quindi il collegamento al tuo programma GCC non riesce.

Come menzionato anche qui puoi forzare CMake a usare MinGW invece di Visual Studio con cmake -G "MinGW Makefiles" ma l'ho provato e non funziona né con MariaDB né con MySQL.

Utilizzo di MSYS2 in MySQL ricevo un errore criptico relativo a OpenSSL mentre sono su MariaDB seguendo il guida ufficiale e quindi utilizzando

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

Devo fare un paio di modifiche manuali, come modificare /src/CArrayImp.h e cambia la riga da 59 a 63 da

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

a

#define ZEROI64 0LL

come 0I64 è definito solo da Visual Studio. Inoltre è necessario rimuovere l'istanza del modello in CArray.cpp ma finisco comunque con un The system cannot find the path specified. messaggio di errore. Allo stesso modo non sono riuscito a farlo compilare in Cygwin.

Alternative del connettore SQL C++

Non ho una soluzione per l'ultimo problema, ma potresti voler dare un'occhiata alle alternative. Puoi scaricare SQLite dal sorgente e compilarlo. Secondo la guida all'installazione dal sorgente è compatibile con MinGW ma è solo leggero . Così dovrebbe essere lo Shareware SQLAPI++ . Secondo loro pagina "Ordine" la versione di prova per Windows è completamente funzionante

Entrambi dovrebbero supportare MySql:ad es. vedi qui .

tl;dr: Usa i connettori MySQL e MariaDB su solo Windows in Visual Studio . Se non puoi utilizzare Visual Studio, dai un'occhiata ai connettori SQL C++ alternativi come SQLite e SQLAPI++ invece.