Qt在Windows平台下编译和使用hiredis库
0x00 hiredis库下载下载地址:https://github.com/redis/hiredis,笔者下载的版本是1.0.0。0x01 使用Qt的MingW编译器编译在hiredis-1.0.0的文件夹内发现了Makefile和CMakeLists.txt文件,是不是很开心,结果很意外。1、 笔者打算直接使用mingw32-make工具执行Makefile文件开始编译hiredis库注意:
目录
1、 笔者打算直接使用mingw32-make工具执行Makefile文件开始编译hiredis库
2、 第一步构建hiredis库失败后,立马想到了使用cmake工具执行CMakeLists.txt文件,重新生成Windows平台下的Makefile文件
a. 使用MS(微软)的nmake工具测试下Makefile文件
b. 使用cmake工具指定Visual Studio 2019编译器执行CMakeLists.txt文件
3、 根据步骤2的分析,我们查看下CMakeLists.txt文件的内容,在Qt Creator建立编译动态库的工程直接编译源码
0x00 hiredis库下载
下载地址:https://github.com/redis/hiredis,笔者下载的版本是1.0.0。
0x01 使用MingW编译器编译
在hiredis-1.0.0的文件夹内发现了Makefile和CMakeLists.txt文件,是不是很开心,结果很意外。
1、 笔者打算直接使用mingw32-make工具执行Makefile文件开始编译hiredis库
执行命令:mingw32-make Makefile
注意:编译出现错误,从错误日志中可以看出编译环境应该是Linux系统下,笔者暂不研究和讲述如何更改Makefile文件使其满足Windows系统,因为这是个复杂的过程。
2、 第一步构建hiredis库失败后,立马想到了使用cmake工具执行CMakeLists.txt文件,重新生成Windows平台下的Makefile文件
执行命令:cmake -G "MinGW Makefiles" CMakeLists.txt
注意:使用cmake工具时指定了MinGW编译器,再一次报错,但笔者可以负责任的告诉你如果指定Visual Studio可以成功。
说明:hiredis-1.0.0的文件夹内Makefile文件是给在Linux系统下构建hiredis库使用,CMakeLists.txt文件是给在Windows系统下构建Visual Studio工程文件使用的。
不服咱就验证下:
a. 使用MS(微软)的nmake工具测试下Makefile文件
执行命令:nmake /f Makefile
b. 使用cmake工具指定Visual Studio 2019编译器执行CMakeLists.txt文件
执行语句:cmake -G "Visual Studio 16 2019" CMakeLists.txt
证明上述结论正确。
3、 根据步骤2的分析,我们查看下CMakeLists.txt文件的内容,在Qt Creator建立编译动态库的工程直接编译源码
结合CMakeLists.txt文件内容和hiredis源码,简要分析下如何构建hiredis动态库。
(1)源码中.c文件有10个,从CMakeLists.txt文件内容中看出构建hiredis库只需要8个.c文件,去掉了ssl.c和test.c文件。
- ssl.c文件需要用到OpenSSL库,它是对Redis客户端和服务器交互时进行数据加密的。
- test.c文件是连接reids数据库的测试代码。
- 源码中的13个.h文件,全部需要使用到的。
(2)使用Qt Creator创建编译hiredis动态库的工程
工程结构如下:
编译发现了18处错误,错误原因都是 undefined reference(未定义的引用)。
错误分析:只有声明和定义,找不到其具体实现。
只使用了.h文件(头文件),没有它的.c或.cpp文件(源文件)或者没有引用其库文件(动态库或者静态库),此处分析的如此透彻,应有掌声。
因为代码中使用winsock编程,即Windows平台下的网络编程套接字,所以代码中需要引用ws2_32库。
ws2_32库是一个Windows Sockets应用程序接口,用于支持Internet和网络应用程序,程序运行时会自动调用ws2_32.dll文件,
它位于系统文件夹中,Windows在查找动态链接库文件时,会先在应用程序当前目录搜索,如果没有找到然后才会搜索Windows所在目录,如果还是没有会搜索system32和system目录。
此时此刻是不是应该恶补下Windows系统编程和网络编程相关的知识呢 ???
4、 编译生成的hiredis库文件如下
0x02 使用hiredis库操作redis数据库
//mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QDebug>
#include <adapters/qt.h>
#include <hiredis.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWidget; }
QT_END_NAMESPACE
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
~MainWidget();
signals:
private slots:
void on_connRedisBtn_clicked();
private:
Ui::MainWidget *ui;
RedisQtAdapter m_adapter;
redisAsyncContext* m_ctx;
void appendMsg_slot(redisReply *reply);
public:
friend void getCallback(redisAsyncContext *, void *, void *);
};
#endif // MAINWIDGET_H
// mainwidget.cpp
#include "mainwidget.h"
#include "ui_mainwidget.h"
//回调函数
void getCallback(redisAsyncContext *ctx, void *r, void *privdata)
{
qDebug() << "getCallback called";
redisReply *reply = static_cast<redisReply*>(r);
MainWidget* mw = static_cast<MainWidget *>(privdata);
//与界面进行数据交互
mw->appendMsg_slot(reply);
if(reply == nullptr || mw == nullptr){
qDebug() << "The reply || mw is nullptr";
return;
}
//打印遍历到的所有键名
for(int i = 0; i < reply->elements; i++){
qDebug() << "key: " << reply->element[i]->str;
}
}
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::MainWidget)
{
ui->setupUi(this);
setWindowTitle("Qt连接Redis数据库Demo");
setFixedSize(570, 454);
ui->textEdit->setReadOnly(true);
ui->textEdit->setTextColor(Qt::red);
ui->textEdit->setFontFamily("Consolas");
ui->textEdit->setFontPointSize(14);
ui->addressLiEdit->setText("localhost");
ui->portLiEdit->setText("6379");
}
MainWidget::~MainWidget()
{
delete ui;
m_adapter.disconnect();
redisAsyncFree(m_ctx);
}
void MainWidget::on_connRedisBtn_clicked()
{
//初始化hiredis上下文
m_ctx = redisAsyncConnect(ui->addressLiEdit->text().toLatin1().data(), ui->portLiEdit->text().toInt());
if(m_ctx->err){
ui->textEdit->append("注意:Redis数据库连接失败!!!");
}
else{
ui->textEdit->append("Redis数据库连接成功-_-");
}
m_adapter.setContext(m_ctx);
redisAsyncCommand(m_ctx, NULL, NULL, "SET Author %s", "键名");
redisAsyncCommand(m_ctx, getCallback, this, "KEYS *");
}
void MainWidget::appendMsg_slot(redisReply *reply)
{
ui->textEdit->append("-----------打印数据键名-----------");
for(int i = 0; i < reply->elements; i++){
ui->textEdit->append(reply->element[i]->str);
}
}
0x03 成果展示
更多推荐
所有评论(0)