Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Bibliotecas MySQL e MariaDB em C++ usando cmake, mingw


Ambos os conectores MySQL e MariaDB (que compartilham a mesma herança ) são destinados a serem compilados e usados ​​apenas com o Visual Studio no Windows . Você encontrará muitas perguntas anteriores no StackOverflow sobre isso. O problema com eles é que eles definem muitas estruturas que já estão definidas na biblioteca padrão e, em seguida, vinculam-se à biblioteca padrão também.

Sugiro que você mudar para o Visual Studio ou para um sistema Linux . Se você precisar usar o GCC no Windows, procure outro conector. Esses problemas não serão resolvidos facilmente. Nesse caso, é improvável que as soluções sejam portáteis e podem não funcionar com versões futuras dos dois conectores. Você pode dar uma olhada nas alternativas SQLite e SQLAPI++ .

Primeiro problema:inteiros de largura fixa

O primeiro problema que você menciona está realmente relacionado aos tipos inteiros de largura fixa e sistemas operacionais de 32 bits definidos nos arquivos de cabeçalho. Existem os tipos inteiros tradicionais como char , short , int , long e long mas adicionalmente os números inteiros de largura fixa acima mencionados.

O conector MySql define o int32_t tipo de dados em config.h e também a biblioteca C++ padrão os define:MySql define o int32_t com o tipo de dados do compilador __int32
typedef __int32 int32_t;
typedef unsigned __int32 uint32_t;

que surpreendentemente acaba sendo o long int tipos de dados
typedef long int int32_t;
typedef long unsigned int uint32_t;

enquanto a biblioteca padrão os define como int normal
typedef int int32_t;
typedef unsigned int uint32_t;

long tipos de dados inteiros são garantidos como sendo de pelo menos 32 bits :Em uma arquitetura de 32 bits, um long int é de 32 bits (como um int ) enquanto para 64 bits eles têm comprimentos diferentes - um long int é de 64 bits e um int é apenas de 32 bits (consulte aqui ). Isso significa que, na verdade, para um sistema de 32 bits, essas definições devem ser idênticas, mas o compilador acha que elas são conflitantes.

O cabeçalho do MySql é envolto por várias definições (coloquei uma explicação ao lado delas para que você possa entender por que as soluções propostas abaixo realmente funcionam) que decidem se os tipos de dados correspondentes devem ser definidos ou não
// 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

Soluções

Com base na estrutura do arquivo de cabeçalho fornecida acima, existem algumas soluções para isso. Alguns podem ser mais viáveis, enquanto outros menos.

  • Claramente você pode não incluir nenhuma definição de tipo em cstdint e stdint.h e viver com as definições do MySql. Na verdade, isso seria bastante limitante, pois mais cedo ou mais tarde provavelmente outro cabeçalho de biblioteca padrão o incluirá e poderá resultar em forçá-lo a não usar a biblioteca padrão, o que pode ser muito limitante.

  • Você pode abandonar completamente a cadeia de ferramentas de compilação de 32 bits que está usando, mudar para um **compilador de 64 bits e compilar para 64 bits . Neste caso, isso não deve acontecer como o cabeçalho config.h no MySql está incluído apenas para sistemas de 32 bits, conforme indicado acima! Se não houver uma boa razão para que seu projeto seja de 32 bits, é isso que eu realmente faria. Falando sobre seu compilador:você parece estar usando o GCC 6.3.0, que foi lançado em 2016 e, na verdade, não suporta totalmente o C++17 padrão de idioma você está dizendo para compilar com CMAKE_CXX_STANDARD 17 em seu arquivo CMake. Você pode querer usar outro compilador mais recente caso queira usar os recursos do C++17 extensivamente. Caso contrário, o C++ 14 também não é tão ruim.

  • Você pode usar o Visual Studio 2010 (versão 1600 ) ou posterior para compilação, pois neste caso o cabeçalho incluirá automaticamente as definições do padrão em vez de definir suas próprias.

  • Você pode definir o sinalizador de pré-processador #define CPPCONN_DONT_TYPEDEF_MS_TYPES_TO_C99_TYPES no topo do seu código (ou dentro do IDE que você está usando para o seu projeto) como se este sinalizador estivesse definido como config.h arquivo não definirá nenhum tipo de dados.

  • Da mesma forma, você também pode resolvê-lo abrindo MYSQLC~1.0/include/jdbc/cppconn/config.h e modificar as diretivas do pré-processador a partir de
    #define HAVE_MS_INT32  1
    #define HAVE_MS_UINT32 1
    

    para
    #define HAVE_MS_INT32  0
    #define HAVE_MS_UINT32 0
    

    Isso desativará as definições correspondentes para todos os programas que você também estiver escrevendo no futuro que incluam esse cabeçalho.

Segundo problema:vinculação a bibliotecas compiladas com o Visual Studio

A segunda mensagem de erro que você recebe está realmente relacionada à vinculação da biblioteca. No Windows, as bibliotecas compiladas com compiladores diferentes geralmente não são compatíveis. Isso significa que um programa compilado com o GCC não pode incluir bibliotecas compiladas com o Visual Studio. No seu caso, a DLL foi compilada com o Visual Studio e, portanto, a vinculação ao seu programa GCC falha.

Como também mencionado aqui você pode forçar o CMake a usar o MinGW em vez do Visual Studio com cmake -G "MinGW Makefiles" mas eu tentei e não funciona com MariaDB nem MySQL.

Usando MSYS2 no MySQL, recebo um erro enigmático relacionado ao OpenSSL enquanto no MariaDB seguindo o guia oficial e depois 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

Eu tenho que fazer algumas modificações manuais, como modificar /src/CArrayImp.h e mude a linha 59 para 63 de
#ifndef _WIN32
# define ZEROI64 0LL
#else
# define ZEROI64 0I64
#endif

para
#define ZEROI64 0LL

como 0I64 é definido apenas pelo Visual Studio. Além disso, é preciso remover a instanciação do modelo em CArray.cpp mas ainda acabo com um The system cannot find the path specified. mensagem de erro. Da mesma forma, não consegui compilar no Cygwin.

Alternativas do conector SQL C++

Não tenho solução para o último problema, mas você pode querer dar uma olhada nas alternativas. Você pode baixar SQLite da fonte e compile-o. De acordo com o guia de instalação da fonte é compatível com MinGW, mas é apenas leve . Assim deve ser o Shareware SQLAPI++ . De acordo com sua página "Pedido" a versão de teste para Windows é totalmente funcional

Ambos devem suportar MySql:e.g. veja aqui .

tl;dr: Use os conectores MySQL e MariaDB no Windows apenas no Visual Studio . Se você não pode usar o Visual Studio, dê uma olhada nos conectores SQL C++ alternativos, como SQLite e SQLAPI++ em vez de.