各位看官这里是目录↓↓↓,点击直达哦~
- 前言
- 一、QLibrary简介
- 二、常用方法
- 2.1 构造函数
- 2.2 设置要访问的动态库——setFileName()
- 2.3 加载动态库——load()
- 2.4 获取动态库的名字——fileName()
- 2.5 解析共享库中的符号——resolve()
 
- 三、示例(Demo)
- 3.1 动态库DLL源码
- 3.2 主程序部分
- 3.3 运行结果
 

前言
本文代码测试环境:
| 编程语言 | 构建套件 | IDE | 操作系统 | 
|---|---|---|---|
| C++ 11 | Desktop Qt 5.9.9 MSVC2013 64bit | Qt Creator 4.11.0 | Windows10 | 
一、QLibrary简介
QLibrary类用于在运行时加载共享库。一个QLibrary对象实例操作一个单独的共享对象文件(也称为“库”或“DLL”)。
QLibrary提供了一种平台独立的方式来访问库中的功能。你可以在构造函数中传递文件名,也可以通过setFileName()显式设置文件名。在加载库时,如果指定的不是绝对路径,
QLibrary会在系统默认的库路径中进行搜索(例如,Unix系统上的LD_LIBRARY_PATH);反之如果在构造时指定了库的绝对路径,则会优先尝试该路径。
二、常用方法
2.1 构造函数
原型:
QLibrary(const QString &fileName, QObject *parent = Q_NULLPTR)
QObject *parent是可选参数,即可省略。
解释:
 构造一个具有指定父对象的库对象,该对象将加载由fileName指定的库。Qt官方建议在fileName中省略文件的扩展名,因为Qlibrary会自动根据平台寻找带有适当后缀的文件,例如在Unix上为".so",在macOS和iOS上为“.dylib”,在Windows上为“.dll”。
2.2 设置要访问的动态库——setFileName()
原型:
void setFileName(const QString &fileName)
解释:
 fileName:要加载的共享库的文件名。它是一个QString类型的参数,可以是一个相对路径或绝对路径(个人建议使用绝对路径)。
2.3 加载动态库——load()
原型:
bool load()
解释:
load()方法用于加载由QLibrary对象当前设置的文件名指定的动态库。如果加载成功,该方法返回true,否则返回false。
2.4 获取动态库的名字——fileName()
原型:
QString fileName() const
解释:
fileName()方法用于获取Qlibrary对象当前所设置的动态库文件名。
这个文件名是在构造QLibrary对象时通过构造函数设置的,或者之后通过setFileName()方法设置的。
使用场景:
 fileName() 方法通常用于调试或日志记录,以确认 QLibrary 对象当前所引用的库文件名是否正确。它也可以用于在动态加载库之前或之后检查文件名,以确保加载的是预期的文件。
2.5 解析共享库中的符号——resolve()
原型:
QFunctionPointer resolve(const char *symbol);
解释:
resolve()方法用于解析动态库中指定的符号,并返回一个指向该符号的函数指针。符号通常指的是库中的函数或全局变量名称。参数:
symbol:要解析的符号的名称,以C字符串(const char *)的形式提供。
如果符号无法解析或库无法加载,则函数返回0。
注意事项:
- 该方法有隐式加载的行为。即:如果动态库尚未被加载,调用resolve()方会隐式地尝试加载动态库。这是通过调用load()方法实现的,调用者不需要关心或处理这个加载过程的细节,QLibrary会在内部处理这些细节。
- 解析的符号必须作为 C函数从库中导出,这意味着如果使用C++编译器编译库,函数需要被封装在extern C块中。
- 在Windows平台上,还需要使用__declspec(dllexport)宏来显示导出函数。
根据注意事项第2、第3条,给出以下示例代码 ↓ ↓ ↓:
  extern "C" 
  {
	  __declspec(dllexport) int avg(int a, int b)
	  {
	      return (a + b) / 2;
	  }
  }
三、示例(Demo)
看完以上内容,写个Demo练习巩固下。
Demo具体内容分为动态库部分和主程序部分:
- 动态库:实现一个加法运算,将传递进来的数值相加,并将结果传回;
- 主程序:使用
QLibrary类加载、使用动态库。
这里粘贴部分主要源码(如.pro文件等,不在这里体现),整个项目见链接:可供学习Qt中QLibrary类的一个Demo,免费下载
3.1 动态库DLL源码
AdditionFunc.h
#ifndef ADDITIONFUNC_H
#define ADDITIONFUNC_H
#if _MSC_VER >= 1600 //VS2015>VS>VS2010, MSVC VER= 10.0 -14.0
#pragma execution_character_set("utf-8")
#endif
#include <QObject>
typedef struct
{
    int a;
    int b;
    int sum;
}T_CoreData;
class AdditionFunc : public QObject
{
    Q_OBJECT
public:
    explicit AdditionFunc(T_CoreData& tCoreData, QObject *parent = nullptr);
    int IntegerAddition(int a, int b);
signals:
};
#endif // ADDITIONFUNC_H
AdditionFunc.cpp
#include <QDebug>
#include "AdditionFunc.h"
AdditionFunc::AdditionFunc(T_CoreData& tCoreData, QObject *parent) : QObject(parent)
{
    tCoreData.sum = IntegerAddition(tCoreData.a, tCoreData.b);
    qDebug() << "我是一个加法运算插件," << "Result = " << tCoreData.sum;
}
int AdditionFunc::IntegerAddition(int a, int b)
{
    return (a+b);
}
PluginInterface.cpp 这个是插件接口文件,主程序加载多个插件时可以使用同一接口文件,简化编程
#include <QDebug>
#include "AdditionFunc.h"
template <class TemPluginClass>
class InitPlugin
{
public:
    InitPlugin()
    {
    }
    ~InitPlugin()
    {
        delete TemPluginClass();
    }
    TemPluginClass* Create(T_CoreData& tCoreData)
    {
        return new TemPluginClass(tCoreData);
    }
};
extern "C"
{
    __declspec(dllexport) QObject* InterfaceFunc(T_CoreData& tCoreData)
    {
        InitPlugin<AdditionFunc> *pCInitPlugin = new InitPlugin<AdditionFunc>;
        qDebug() << "InterfaceFunc() run..." ;
        return pCInitPlugin->Create(tCoreData);
    }
}
3.2 主程序部分
MyMainWindow.h
#ifndef MYMAINWINDOW_H
#define MYMAINWINDOW_H
#include <QMainWindow>
#include <QLibrary>
#if _MSC_VER >= 1600 //VS2015>VS>VS2010, MSVC VER= 10.0 -14.0
#pragma execution_character_set("utf-8")
#endif
QT_BEGIN_NAMESPACE
namespace Ui { class MyMainWindow; }
QT_END_NAMESPACE
typedef struct
{
    int a;
    int b;
    int sum;
}T_CoreData;
class MyMainWindow : public QMainWindow
{
    Q_OBJECT
public:
    MyMainWindow(QWidget *parent = nullptr);
    ~MyMainWindow();
    int runUser();
public:
    QLibrary *m_CQLibrary;
private:
    Ui::MyMainWindow *ui;
    T_CoreData m_tCoreData;
};
#endif // MYMAINWINDOW_H
MyMainWindow.cpp
#include <QDebug>
#include "MyMainWindow.h"
#include "ui_MyMainWindow.h"
typedef QObject* (*PluginInterface)(T_CoreData& tCoreData);
MyMainWindow::MyMainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MyMainWindow)
{
    ui->setupUi(this);
    m_tCoreData.a = 6;
    m_tCoreData.b = 7;
    runUser();
}
MyMainWindow::~MyMainWindow()
{
    delete ui;
    delete m_CQLibrary;
}
int MyMainWindow::runUser()
{
    PluginInterface pPluginInterface;       // 声明接口函数指针
    QString QStrPluginsPath = QCoreApplication::applicationDirPath() + "/../Plugins";
    QStrPluginsPath += "/PluginAddition";
    m_CQLibrary = new QLibrary(QStrPluginsPath);
    if (m_CQLibrary->load())  // 加载成功
    {
        pPluginInterface = (PluginInterface)m_CQLibrary->resolve("InterfaceFunc");
        if (nullptr != pPluginInterface)
        {
            qDebug() << "插件创建成功,插件名字是:" << m_CQLibrary->fileName();
            pPluginInterface(m_tCoreData);
            qDebug() << "主程序打印计算结果:" << m_tCoreData.sum;
        }
    }
    else        // 加载失败
    {
        qDebug() << "插件加载失败!"<< m_CQLibrary->load();
    }
    return 0;
}
main.cpp
#include "MyMainWindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MyMainWindow w;
    w.show();
    return a.exec();
}
3.3 运行结果



















![C语言程序设计-[11] 循环结构嵌套](https://i-blog.csdnimg.cn/direct/388ae930d6a444eab3034923f53a80e2.png)
