sql >> Base de Datos >  >> RDS >> Mysql

Biblioteca MySQL y MariaDB en C++ usando cmake, mingw

Tanto los conectores MySQL como MariaDB (que comparten la misma herencia ) están diseñados para ser compilados y utilizados con Visual Studio solo en Windows . Encontrará muchas preguntas anteriores sobre StackOverflow al respecto. El problema con ellos es que definen muchas estructuras que ya están definidas en la biblioteca estándar y luego también se vinculan a la biblioteca estándar.

Le sugiero que cambie a Visual Studio o a un sistema Linux . Si tiene que usar GCC en Windows, busque otro conector. Estos problemas no se resolverán fácilmente. Si es así, es poco probable que las soluciones sean portátiles y es posible que no funcionen con futuras versiones de los dos conectores. Puede echar un vistazo a las alternativas SQLite y SQLAPI++ .

Primer problema:enteros de ancho fijo

El primer problema que mencionas en realidad está relacionado con los tipos enteros de ancho fijo y sistemas operativos de 32 bits definidos en los archivos de encabezado. Existen los tipos enteros tradicionales como char , short , int , long y long long pero además los enteros de ancho fijo antes mencionados.

El Conector MySql define el int32_t tipo de datos en config.h y también la biblioteca estándar de C++ los define:MySql define el int32_t con el tipo de datos del compilador __int32

typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;

que sorprendentemente resulta ser el long int tipos de datos

typedef long int int32_t;
typedef long unsigned int uint32_t;

mientras que la biblioteca estándar los define como int regulares

typedef int int32_t;
typedef unsigned int uint32_t;

long tipos de datos enteros están garantizados para ser de al menos 32 bits :En una arquitectura de 32 bits, un long int es de 32 bits (al igual que un int ) mientras que para 64 bits tienen diferentes longitudes:un long int es de 64 bits y un int es solo de 32 bits (ver aquí ). Esto significa que, en realidad, para un sistema de 32 bits, estas definiciones deberían ser idénticas pero, sin embargo, el compilador cree que están en conflicto.

El encabezado MySql está envuelto por varias definiciones (puse una explicación junto a ellas para que pueda entender por qué las soluciones propuestas que se dan a continuación realmente funcionan) que deciden si los tipos de datos correspondientes deben definirse o no

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

Soluciones

Según la estructura del archivo de encabezado anterior, hay un par de soluciones para esto. Algunos pueden ser más viables mientras que otros menos.

  • Claramente, podría no incluir ninguna de las definiciones de tipo en cstdint y stdint.h y vive con las definiciones de MySql. En realidad, esto sería bastante limitante, ya que tarde o temprano es probable que otro encabezado de biblioteca estándar lo incluya y podría obligarlo a no usar la biblioteca estándar en absoluto, lo que podría ser muy limitante.

  • Podría abandonar por completo la cadena de herramientas de compilación de 32 bits que está utilizando, cambiar a un **compilador de 64 bits y compilar para 64 bits . En este caso esto no debería suceder ya que el encabezado config.h en MySql solo se incluye para sistemas de 32 bits como se indicó anteriormente. Si no hay una buena razón para que su proyecto sea de 32 bits, eso es lo que realmente haría. Hablando de su compilador:parece que está usando GCC 6.3.0, que se lanzó en 2016 y en realidad no es completamente compatible con C++17 estándar de idioma le estás diciendo que compile con CMAKE_CXX_STANDARD 17 en su archivo CMake. Es posible que desee usar otro compilador más nuevo en caso de que quiera usar las funciones de C++ 17 de forma extensiva. De lo contrario, C++14 tampoco es tan malo.

  • Podrías usar Visual Studio 2010 (versión 1600 ) o posterior para la compilación ya que en este caso el encabezado incluirá automáticamente las definiciones del estándar en lugar de definir las suyas propias.

  • Podrías definir el indicador de preprocesador #define CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES encima de su código (o dentro del IDE que está utilizando para su proyecto) como si este indicador estuviera configurado en config.h el archivo no definirá ningún tipo de datos.

  • Del mismo modo, también podría resolverlo abriendo MYSQLC~1.0/include/jdbc/cppconn/config.h y modificar las directivas del preprocesador de

    #define HAVE_MS_INT32  1
    #define HAVE_MS_UINT32 1
    

    a

    #define HAVE_MS_INT32  0
    #define HAVE_MS_UINT32 0
    

    Esto desactivará las definiciones correspondientes para todos los programas que también esté escribiendo en el futuro que incluyan este encabezado.

Segundo problema:vinculación a bibliotecas compiladas con Visual Studio

El segundo mensaje de error que recibe en realidad está relacionado con la vinculación de la biblioteca. En Windows, las bibliotecas compiladas con diferentes compiladores generalmente no son compatibles. Esto significa que un programa compilado con GCC no puede incluir bibliotecas compiladas con Visual Studio. En su caso, la DLL se compiló con Visual Studio y, por lo tanto, falla la vinculación a su programa GCC.

Como también se menciona aquí puede obligar a CMake a usar MinGW en lugar de Visual Studio con cmake -G "MinGW Makefiles" pero lo he probado y no funciona ni con MariaDB ni con MySQL.

Usando MSYS2 en MySQL obtengo un error críptico relacionado con OpenSSL mientras estoy en MariaDB siguiendo el guía oficial y luego usando

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

Tengo que hacer un par de modificaciones manuales, como modificar /src/CArrayImp.h y cambia la línea 59 a la 63 de

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

a

#define ZEROI64 0LL

como 0I64 solo lo define Visual Studio. Además, se debe eliminar la instanciación de la plantilla en CArray.cpp pero todavía termino con un The system cannot find the path specified. mensaje de error. Del mismo modo, no pude compilarlo en Cygwin.

Alternativas al conector SQL C++

No tengo solución para el último problema, pero es posible que desee echar un vistazo a las alternativas. Puede descargar SQLite de la fuente y compilarlo. De acuerdo con la guía de instalación de la fuente es compatible con MinGW pero solo es ligero . Así debería ser Shareware SQLAPI++ . Según su página de "Pedido" la versión de prueba para Windows es completamente funcional

Ambos deben ser compatibles con MySql:p. ver aquí .

tl;dr: Use los conectores MySQL y MariaDB en Windows en Visual Studio solamente . Si no puede usar Visual Studio, eche un vistazo a los conectores SQL de C++ alternativos como SQLite y SQLAPI++ en su lugar.