Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connecting to MySQL in C++

I am trying to learn C++ and I am having a bit of nightmare doing a test where I connect to a MySQL database.

I've had issues with the MySQL connector not linking properly then was getting issues related to relocation truncated to fitr_x86_64_32 against symbol.

I think I have fixed that by adding a compiler flag and now the app successfully builds and links.

When I run the app, it gets as far as calling get_driver_instance but then it exits. No exception is thrown, no errors nothing just exit code 0.

Below is my DBManager class

#include "DBConnectionManager.h"

using namespace std;

DBConnectionManager::DBConnectionManager() {
    cout << "Starting DBConnectionManager - Updated" << endl;
    try {
        cout << "Getting driver instance" << endl;
        driver = get_driver_instance();
        cout << "Got driver instance" << endl;
        conn = driver->connect("tcp://127.0.0.1:3306", "root", "password");
        conn->setSchema("bugs");
        cout << "Connected to database" << endl;
    }
    catch (SQLException ex) {
        cout << "Error connecting to DB: " << ex.what() << endl;
    }
    catch (...) {
        cout << "Something has gone wrong" << endl;
    }
}

Below is the header file

#ifndef MYSQLTEST_DBCONNECTIONMANAGER_H
#define MYSQLTEST_DBCONNECTIONMANAGER_H
#include <driver.h>
#include <exception.h>
#include <resultset.h>
#include <statement.h>

using namespace sql;

class DBConnectionManager
{
private:
    sql::Driver *driver;
    sql::Connection *conn;
    sql::Statement *statement;
    sql::ResultSet *res;
public:
    DBConnectionManager();
    void performSql();
};
#endif //MYSQLTEST_DBCONNECTIONMANAGER_H

Below is my main method

#include "DBConnectionManager.h"

int main() {
    DBConnectionManager dbConnectionManager;
    dbConnectionManager.performSql();
    return 0;
}

Below is my CMakeLists.txt file

cmake_minimum_required(VERSION 3.6)
project(MySQLTest)

include_directories("C:\\Program Files\\MySQL\\MySQL Connector C++ 1.1.7\\include\\cppconn" "C:\\Program Files\\MySQL\\MySQL Connector C++ 1.1.7\\lib\\opt")

SET(GCC_COVERAGE_LINK_FLAGS    "-m64 -Wl,--image-base -Wl,0x10000000 -lpthread -pthread")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -m64 -Wl,--image-base -Wl,0x10000000 -lpthread -pthread ")

set(SOURCE_FILES main.cpp DBConnectionManager.cpp)
add_executable(MySQLTest ${SOURCE_FILES})
add_library(mysqlcppconn.lib)

set_target_properties(MySQLTest PROPERTIES LINKER_LANGUAGE CXX)
set_target_properties(mysqlcppconn.lib PROPERTIES LINKER_LANGUAGE CXX)

target_link_libraries(MySQLTest "C:\\Program Files\\MySQL\\MySQL Connector C++ 1.1.7\\lib\\opt\\mysqlcppconn.lib")

When I create the instance of my DBConnectionManager class it successfully calls the query and prints Starting DBConnectionManager - Updated followed by Getting Driver Instance but then it exits with Process finished with exit code 0 with no clues as to what went wrong.

Update

I'm finally getting somewhere. I found there are some MySQL client libraries within Cygwin so I have download them and referenced them in the cmake file.

My cmake file now looks like this:

cmake_minimum_required(VERSION 3.6)
project(MySQLTest)

SET(CPPCONN_PUBLIC_FUNC=)

SET(GCC_COVERAGE_LINK_FLAGS    "-g -m64 -DCPPCONN_PUBLIC_FUNC= -Dmysqlcppconn_EXPORTS -lpthread -pthread -Wl,--image-base -Wl,0x10000000  -lz")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCPPCONN_PUBLIC_FUNC= -Dmysqlcppconn_EXPORTS -std=c++11 -g -m64 -Wl,--image-base -Wl,0x10000000  -lpthread -pthread  -lz")

include_directories("C:/mysql_connector/include")
include_directories("C:/boost_1_61_0")

set(BOOST_INCLUDE_DIR C:/boost_1_61_0)
set(BOOST_LIBRARY_DIR C:/boost_1_61_0/libs)
set(SOURCE_FILES main.cpp DBConnectionManager.cpp)

add_executable(MySQLTest ${SOURCE_FILES})

find_package(Boost COMPONENTS REQUIRED)

link_directories(C:/mysql_connector/lib)

target_link_libraries(MySQLTest "C:/mysql_connector/lib/mysqlcppconn.dll"  "C:/Program Files/MySQL/MySQL Server 5.7/lib/libmysql.dll" "C:/mysql_connector/lib/libmysqlclient.dll.a" "C:/mysql_connector/lib/libmysqlclient_r.dll.a" ${Boost_LIBRARY_DIR})

Notice how I have linked the libraries libmysqlclient.dll.a and libmysqlclient_r.dll.a which is what I got from Cygwin.

When I run the app now it successfully gets the driver instance and to the console is outputted

Starting DBConnectionManaged - Updated
Getting driver instance
Got driver instance

But when I try and connect with driver->connect I then get the following error

0 [main] MySQLTest 2976 C:\Users\Chris\.CLion2016.2\system\cmake\generated\MySQLTest-8702ae13\8702ae13\Debug\MySQLTest.exe: *** fatal error - Internal error: TP_NUM_C_BUFS too small: 50

When I put it through the debugger, it fails on the driver->connect with

gdb: unknown target exception 0xe06d7363 at 0x7fff11347788

Program received signal ?, Unknown signal.
0x00007fff11347788 in RaiseException () from /cygdrive/c/WINDOWS/System32/KERNELBASE.dll

Update 2

Everything I've read points the mysql connector binaries should work fine, so I started again. Below is now the contents of my cmake file

cmake_minimum_required(VERSION 3.6)
project(MySQLTest)


#add_compile_options("-v")

SET(GCC_COVERAGE_LINK_FLAGS )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(BOOST_INCLUDE_DIR C:/boost_1_61_0)
set(BOOST_LIBRARY_DIR C:/boost_1_61_0/libs)

include_directories("C:/Program\ Files/MySQL/MySQL\ Connector\ C++\ 1.1.7/include" "C:/Program\ Files/MySQL/MySQL\ Connector\ C++\ 1.1.7/include/cppconn" ${BOOST_INCLUDE_DIR})


set(SOURCE_FILES main.cpp DBConnectionManager.cpp)

add_executable(MySQLTest ${SOURCE_FILES})

find_package(Boost COMPONENTS REQUIRED)

link_directories(C:/Program\ Files/MySQL/MySQL\ Connector\ C++\ 1.1.7/lib/opt)

target_link_libraries(MySQLTest C:/Program\ Files/MySQL/MySQL\ Connector\ C++\ 1.1.7/lib/opt/mysqlcppconn.lib ${Boost_LIBRARY_DIR})

Now when I compile I get the original error

C:/Program Files/MySQL/MySQL Connector C++ 1.1.7/lib/opt/mysqlcppconn.lib(mysqlcppconn.dll.b):(.text+0x2): relocation truncated to fit: R_X86_64_32 against symbol `__imp_get_driver_instance' defined in .idata$5 section in C:/Program Files/MySQL/MySQL Connector C++ 1.1.7/lib/opt/mysqlcppconn.lib(mysqlcppconn.dll.b)

That sounds like to me like my app is compiling as 32 bit instead of 64 bit. As a test I ran the following code:

cout << "Int size is: " << sizeof(int) << endl;

The code above prints 4 (shouldn't it be 8 if it was compiled as 64 bit).

If my thinking is correct, why isn't it compiling it as 64 bit, I've tried setting the compiler flag -m64 but makes no difference. I've installed the Cygwinx64 as well which CLion is using.

like image 207
Boardy Avatar asked Sep 27 '16 17:09

Boardy


People also ask

Can we connect MySQL with C?

MySQL database is available on most important OS platforms. It runs on BSD Unix, Linux, Windows, or Mac OS. To be able to compile C examples, we need to install the MySQL C development libraries. The above line shows how we can do it on Debian based Linux.

Can we connect C with database?

You can then add a new C source file and replace it with this content. Using the ODBC APIs SQLAllocHandle, SQLSetConnectAttr, and SQLDriverConnect, you should be able to initialize and establish a connection to your database.

Can we connect MySQL with C++?

MySQL Connector/C++ 8.0 is a MySQL database connector for C++ applications that connect to MySQL servers. Connector/C++ can be used to access MySQL servers that implement a document store, or in a traditional way using SQL statements.


2 Answers

You can use MySQL Connector C++

This is how to configure using Cmake

cmake_minimum_required(VERSION 3.7)

project(projectname)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

Include the dirs where you extracted the mysql-connector-cpp - download

include_directories(/usr/local/include/mysql-connector-cpp/include)

Create a cmake variable containing the project source files

set(SOURCE_FILES main.cpp)

Create your executable

add_executable(projectname ${SOURCE_FILES})

Link after creating executable

target_link_libraries(projectname mysqlcppconn)

Your CMakeList should at least have this or look like this in this order

cmake_minimum_required(VERSION 3.7)
project(projectname)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(/usr/local/include/mysql-connector-cpp/include)
set(SOURCE_FILES main.cpp)
add_executable(projectname ${SOURCE_FILES})
target_link_libraries(projectname mysqlcppconn)
like image 111
Victor Mwenda Avatar answered Oct 24 '22 05:10

Victor Mwenda


You can use mysql++ library to connect to mysql from c++.
For that install mysql++,
(Ubuntu)

sudo apt-get install mysql-server mysql-client
sudo apt-get install libmysqlclient-dev libmysql++-dev libmysqlcppconn-dev

(Mac)

brew install mysql++

include library by adding,

/usr/include/mysql++
/usr/include/mysql

and add linkers,

-lmysqlpp -lmysqlclient

Example code,

#include <iostream>
#include <string>
#include <mysql++.h>
#include <mysql.h>

#define dbname "dbname"
#define server "localhost"
#define user "username"
#define pass "password"

using namespace std;
using namespace mysqlpp;

int main() {
    Connection con(true);
    try {
        con.connect(dbname, server, user, pass);
        cout << "Connected to database\n";
        string s = "SELECT * FROM mirrors_mee WHERE id=1";
        Query q = con.query(s);
        StoreQueryResult sq = q.store();
        StoreQueryResult::iterator it;
        it = sq.begin();
        while (it != sq.end()) {
            Row row = *it;
            cout << row[5] << " " << row[6] << " " << row[7] << endl;
            it++;
        }
    } catch (Exception &e) {
        cout << e.what() << endl;
    }
    return 0;
}

You will get full documentation of the library here.

like image 22
Md Samiul Alim Sakib Avatar answered Oct 24 '22 05:10

Md Samiul Alim Sakib