目录

 

0x00 hiredis库下载

0x01 使用MingW编译器编译

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建立编译动态库的工程直接编译源码

4、 编译生成的hiredis库文件如下

0x02 使用hiredis库操作redis数据库

0x03 成果展示


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 成果展示

呈上源码:https://github.com/XiaoQinEr/QtHiRedis

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐