问题描述

在我们结合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:

新手一枚,如果觉得有疑问可以私信询问!

如果上述文章内容有讲得不正确或者不清楚的地方,欢迎留言评论区或者私信!

最后,能给我一个小小的赞或者关注吗😘

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐