在Qt中使用原生C++的Mysql库(无需重新编译动态链接库)
问题描述
在我们结合Mysql开发Qt的时候,往往会希望可以复用原有的Mysql后端代码逻辑实现代码的复用(毕竟人家mysql官方文档中关于C++的语法文档写得很好,或者懒得学QSqlDatabase的语法🥲)。
可是Qt(Qt6.5.3)中默认不搭载Mysql的驱动,如果真要折腾可以借鉴此视频(2020版本)qt的mysql驱动编译_哔哩哔哩_bilibili。
此视频中需要在Qt Maintain中下载好源代码文件,之后前往QtMaintainer下载源代码文件,然后找到mysql.pro文件,然后进行编译。但实操之后发现存在两个问题
1. 年代久远,这个pro文件现在已经没有了。即使手动输入,也找不到对应依赖
2. 版本问题,当前环境Qt里编译生成的版本是否能和其他开发者相同?
此方案在较新版本已然无法行通。
在本文中,我们直接将Mysql原有库搬运到Qt项目下,并通过QMake进行链接,最终实现使用原有C++-Mysql代码便可完美移植到Qt上的效果。
问题解决
前置工作
创建lib和_include文件夹放置相关库
在原有项目文件夹中,创建两个新的文件夹lib和_include
1. lib 用于存放 mysqlclient.lib (原本存放在mysql的路径之下)
2. _include(直接用include会因为是关键字从而导致无法识别) ,是 mysql对应的实现目录(也将其复制过来)
lib文件夹
前往mysql的目录下(路径类似于C:\Program Files\MySQL\MySQL Server 8.0\lib),找到其中的libmysql.lib和mysqlclient.lib,将其复制到lib文件夹下。

_include文件夹
前往mysql/include(路径类似于C:\Program Files\MySQL\MySQL Server 8.0\include),将其中内容拷贝至_include文件夹下。

最终项目整体结构如下(注意此处应该严格按照此结构,后续设置.pro文件时会有影响)

设置pro文件
在我们的.pro文件下添加以下代码,将lib和_include文件夹包含进来
#-----------------------------------
LIBS += -lmysqlclient
### 1. Add the llibmysql
win32: LIBS += -L$$PWD/lib/ -llibmysql
### 2. Add the libmysqlclient
win32: LIBS += -L$$PWD/lib/ -lmysqlclient
INCLUDEPATH += $$PWD/_include
DEPENDPATH += $$PWD/_include
#------------------------------------
正常使用C++语法测试mysql是否正常工作
backdb.h(后端数据库头文件)
#ifndef BACKDB_H
#define BACKDB_H
#pragma once
#include <stdio.h>
#include <mysql.h>
#include <iostream>
#include <QString>
#include <QVector>
class BackDB
{
private:
MYSQL mysql;//The MySql object
const char* host; // MySQL server host 地址(阿里云中为公网地址)
const char* user; // MySQL username
const char* password; // MySQL password
const char* database; // MySQL database name
unsigned int port = 3306; // MySQL port (default is 3306)
const char* unix_socket = nullptr; // Unix socket (can be nullptr for TCP/IP)
unsigned long client_flag = 0; // Connection flags (usually 0)
public:
//----------Consturctor----------
BackDB(const char* _host, const char* _user, const char* _password, const char* _database,
unsigned int _port = 3306, const char* _unix_socket = nullptr, unsigned long _client_flag = 0);
//----------Consturctor----------
BackDB();
MYSQL_RES* query(const char* query);
};
#endif // BACKDB_H
backdb.cpp(后端数据库源文件)
#include "backdb.h"
#include "QString"
#include <string>
#include <QDebug>
//----------Constructor----------
//Constructor , the basic information is host+user+password+database
BackDB::BackDB(const char* _host, const char* _user, const char* _password, const char* _database,
unsigned int _port, const char* _unix_socket , unsigned long _client_flag)
:host(_host), user(_user), password(_password), database(_database), port(_port), unix_socket(_unix_socket)
, client_flag(_client_flag)
{
mysql_init(&mysql);
// Connect to MySQL database using mysql_real_connect
if (mysql_real_connect(&mysql, host, user, password, database, port, unix_socket, client_flag))
{
std::cout << "Connected to MySQL database successfully!" << std::endl;
std::cout << "Database Name:" << database << std::endl;
}
else {
std::cerr << "Connection error: " << mysql_error(&mysql) << std::endl;
}
}
//----------Constructor----------
//----------Basic Operations----------
//Return the MYSQL_RES Pointer of the return result
MYSQL_RES* BackDB::query(const char* query)
{
int ret = mysql_query(&mysql, query);
if (ret != 0) {
std::cerr << "Query execution failed: " << mysql_error(&mysql) << std::endl;
return nullptr;
}
else {
MYSQL_RES* result = mysql_store_result(&mysql);
if (result == nullptr) {
std::cout << "Haven't received the result set(not necessary) " << std::endl;
}
return result;
}
}
//----------Basic Operations----------
main.cpp
#include "mainwindow.h"
#include "backdb.h"
#include <QApplication>
int main(int argc, char *argv[])
{
// QApplication a(argc, argv);
// MainWindow w;
BackDB testDB("127.0.0.1", "test", "123456" , "test",
3306, nullptr, 0);
MYSQL_RES* result=testDB.query("SELECT * FROM pet");
int num_fields = mysql_num_fields(result);
MYSQL_ROW row;
while ((row = mysql_fetch_row(result)) != nullptr) {
for (int i = 0; i < num_fields; ++i) {
if (row[i] != nullptr) {
std::cout << row[i] << "\t\t";
} else {
std::cout << "NULL\t";
}
}
std::cout << std::endl;
}
// w.show();
// return a.exec();
}
测试结果
设置完这三个文件后,整体项目结构应为

本地已有数据库test中的pet表内容

此时运行main.cpp,观察下方Aplication Output观察运行结果

发现已经正常连接上,至此Qt和MySql连接完毕。
全程不用再进行驱动编译,也没有使用QSqlDatabase。
最后
1.出现ambitious definition of byte错误
检查C++代码,确保没有使用using namespace std,而是加上std:: 进行命名空间的限定
2.如何用命令行进行编译生成exe
g++ -Wl,-O1 -Wl,-rpath-link,/usr/lib/x86_64-linux-gnu -o
VirtualStock backdb.o buyin.o chartspline.o enroll.o global.o login.o main.o mainwindow.o marketnews.o personpage.o portfolio.o record.o stock.o user.o usermanage.o
virtualcurrency.o widget.o moc_buyin.o moc_chartspline.o moc_enroll.o moc_login.o
moc_mainwindow.o moc_personpage.o moc_widget.o
/usr/lib/x86_64-linux-gnu/libQt6Charts.so
/usr/lib/x86_64-linux-gnu/libQt6OpenGLWidgets.so
/usr/lib/x86_64-linux-gnu/libQt6Widgets.so
/usr/lib/x86_64-linux-gnu/libQt6OpenGL.so
/usr/lib/x86_64-linux-gnu/libQt6Gui.so
/usr/lib/x86_64-linux-gnu/libGLX.so
/usr/lib/x86_64-linux-gnu/libOpenGL.so
/usr/lib/x86_64-linux-gnu/libQt6Sql.so
/usr/lib/x86_64-linux-gnu/libQt6Core.so
-lpthread
-lGLX -lOpenGL
-lmysqlclient
一般而言如果pro文件书写得当(在pro文件中加上LIBS += -lmysqlclient),qmake会帮你做这部分工作。如若没有,在类似上面的命令下加上-lmysqlclient。
3.可以把lib和_include文件夹放到其他位置吗?
可以啊,注意更改pro文件中的PWD该行的内容即可。PWD对应pro文件所在位置。
Tips:
新手一枚,如果觉得有疑问可以私信询问!
如果上述文章内容有讲得不正确或者不清楚的地方,欢迎留言评论区或者私信!
最后,能给我一个小小的赞或者关注吗😘
更多推荐
所有评论(0)