在Linux系统中动态库后缀名为.so; 在Windows系统中动态库后缀名为.dll

我们在进行模块化设计开发过程中,往往会将一组功能,封装成一个动态库,从哪儿在整个软件开发升级改特定功能时,只需要修改该动态库,修改完成后替换该动态库即可;

这里提到动态库,它的优缺点如下:

优点

1、可实现不同进程间的资源共享;

2、动态库升级简单,只需要替换库文件,无需重新编译应用程序;

3、模块化耦合性小,大规模软件开发过程中相互独立;

4、可以控制动态库的加载跟卸载;

缺点

1、速度相对静态库要慢;

2、打包的时候需要连同动态库一起打包

动态库的使用方式可分为两种

一、动态库的隐式调用

(动态库新建省略)

1、在指定工程中右键添加库

        

 

 

 

2、使用库文件

 

 二、显示调用动态库

1、构建库函数

UnderLayerBehavior_global.h
#ifndef UNDERLAYERBEHAVIOR_GLOBAL_H
#define UNDERLAYERBEHAVIOR_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(UNDERLAYERBEHAVIOR_LIBRARY)
#  define UNDERLAYERBEHAVIOR_EXPORT Q_DECL_EXPORT
#else
#  define UNDERLAYERBEHAVIOR_EXPORT Q_DECL_IMPORT
#endif

#endif // UNDERLAYERBEHAVIOR_GLOBAL_H
underlayerbehavior.h
#ifndef UNDERLAYERBEHAVIOR_H
#define UNDERLAYERBEHAVIOR_H

#include "UnderLayerBehavior_global.h"
#include <QObject>

class UNDERLAYERBEHAVIOR_EXPORT UnderLayerBehavior:public QObject
{
    Q_OBJECT
public:
    UnderLayerBehavior(QObject* parent = nullptr);
    ~UnderLayerBehavior();
    void setDataModel(int id);
};

//此处初始化插件,显示调用此处必须添加调用接口
extern "C"{
    UNDERLAYERBEHAVIOR_EXPORT QObject* getObjPtr();

    UNDERLAYERBEHAVIOR_EXPORT int pVerify(int);

    UNDERLAYERBEHAVIOR_EXPORT void setDataModule(int model);
}

#endif // UNDERLAYERBEHAVIOR_H
underlayerbehavior.cpp
#include "underlayerbehavior.h"

//插件接口变量
UnderLayerBehavior Qunder;

UnderLayerBehavior::UnderLayerBehavior(QObject *parent):QObject(parent)
{
}

UnderLayerBehavior::~UnderLayerBehavior(){}

void UnderLayerBehavior::setDataModel(int id)
{

}

UNDERLAYERBEHAVIOR_EXPORT QObject* getObjPtr()
{
    return (QObject*)(&Qunder);
}

//验证dll
UNDERLAYERBEHAVIOR_EXPORT int pVerify(int a)
{
    return a;
}

UNDERLAYERBEHAVIOR_EXPORT void setDataModule(int model)
{
    Qunder.setDataModel(model);
}

2、使用该动态库接口

behaviormanager.h
#ifndef BEHAVIORMANAGER_H
#define BEHAVIORMANAGER_H

#include "BehaviorManager_global.h"
#include <QObject>
#include <QLibrary>
#include <QMap>

class BEHAVIORMANAGER_EXPORT BehaviorManager:public QObject
{
    Q_OBJECT
public:
    BehaviorManager(QObject* parent = nullptr);
    ~BehaviorManager();
    //注册加载所有DLL
    bool registerAllLibrary();
    //卸载所有Dll
    bool unInstallAllLibaray();
    //初始化
    void initModel();
private:
    //获取指定目录下的所有DLL文件名
    QStringList findAllDll(QString path);

    QMap<QString, QLibrary*> behaviorLibMap;
};

#endif // BEHAVIORMANAGER_H

behaviormanager.cpp

#include "behaviormanager.h"

#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>

//校验dll
typedef  int (*func_verify)(int);

//获取库函数对象
typedef QObject* (*func_dllObj)();

BehaviorManager::BehaviorManager(QObject *parent):QObject(parent)
{}

BehaviorManager::~BehaviorManager(){}

//注册加载所有DLL
bool BehaviorManager::registerAllLibrary()
{
    //获取可执行文件所在文件夹路径
    QString appPath = QCoreApplication::applicationDirPath();
    QStringList dllNameLst = findAllDll(appPath+"Behavior");

    for(QString dllName:dllNameLst)
    {
        QLibrary* curLibrary = new QLibrary("Behavior"+dllName);
        if(curLibrary->load())
        {
            //校验库文件
            func_verify pfuncVerify = (func_verify)(curLibrary->resolve("pVerify"));//调用库的接口
            if(0 != pfuncVerify(0))
            {
                delete curLibrary;
                curLibrary = nullptr;
                continue;
            }
            behaviorLibMap.insert(dllName, curLibrary);
            //dll加载成功
        }
        else{
            //dll 加载失败
        }
    }
    if(0 == behaviorLibMap.size())
    {
        return false;
    }
    return true;
}

 //卸载所有Dll
bool BehaviorManager::unInstallAllLibaray()
{
    for(QLibrary* pLibrary:behaviorLibMap.values())
    {
        if(pLibrary->isLoaded())
        {
            //libray被加载
            pLibrary->unload();//卸载
        }

    }
}

//使用库函数定义对象
void BehaviorManager::initModel()
{
    auto itor = behaviorLibMap.begin();
    while (itor != behaviorLibMap.end()) {
        QLibrary* pLibrary = itor.value();
        func_dllObj pDllObj = (func_dllObj)(pLibrary->resolve("getObjPtr"));
        QObject* Obj = pDllObj();
        if(nullptr == Obj)
        {
            //判断对象是否为空
        }
    }
}

//获取指定目录下的所有DLL文件名
QStringList BehaviorManager::findAllDll(QString path)
{
    QStringList dllNameLst;
    QDir fDir(path);
    //设置文件过滤
    fDir.setFilter(QDir::Files);
    QFileInfoList fileLst = fDir.entryInfoList();
    for(int i=0; i<fileLst.size();i++)
    {
        //获取后缀名
        QString filetype = fileLst.at(i).suffix();
        //对比后缀名 dll 忽略大小写
        if(0 == filetype.compare("dll", Qt::CaseInsensitive))
        {
            dllNameLst.append(fileLst.at(i).baseName());
        }
    }
    return  dllNameLst;
}

这里就是动态库的基本用法!

Logo

更多推荐