QT-动态链接库动态加载和静态加载方法详解

1、先说明本文要实现的功能:

(1)生成一个动态链接库;

(2)隐式加载动态链接库,需要的文件:*.h(非必须文件,如果不使用*.h文件,那么调用程序所需要的函数或是类就需要自己声明,所以说建议直接使用动态链接库的*.h文件。如果使用别人的动态链接库没有*.h文件那只有自己在调用程序中声明了);*.dll文件(必须有);*.lib文件(必须有)。

(3)使用QLibrary()动态加载,*.h同2;*.dll(必须有);*.lib(不使用)。

2.项目文件构成:

QT-动态链接库动态加载和静态加载方法详解_第1张图片

3、编写动态链接库:

QtCtreater :新建项目---Library---C++Library ...其他默认;但是在Details这一步我们要选择SharedLibrary。

#ifndef MYDLL_H
#define MYDLL_H

#include "mydll_global.h"

//baseClass类在显式调用时使用
class  baseClass
{
public:
    baseClass();
    virtual ~baseClass();
    virtual int add(int a, int b) = 0;
};

class MYDLL_EXPORT Mydll : public baseClass
{
public:
    Mydll();
    int add(int a, int b);
};


//显示调用动态库时需要使用使用
extern "C"{
    MYDLL_EXPORT baseClass* getDllObject(); //获取类Dll的对象
    MYDLL_EXPORT void releseDllObject(baseClass* pdll); //删除类Dll的对象
}

#endif // MYDLL_H
#include "mydll.h"
#include 

Mydll::Mydll()
{
    qDebug()<<"Mydll::Mydll()";
}

int Mydll::add(int a, int b)
{
    return a + b;
}

baseClass *getDllObject()
{
    return (baseClass*)new Mydll();
}

void releseDllObject(baseClass * pdll)
{
    if(pdll)
    {
        delete pdll;
        pdll = nullptr;
    }
}

baseClass::baseClass()
{

}

baseClass::~baseClass()
{

}

pro文件的配置主要:

QT -= gui

TEMPLATE = lib
DEFINES += MYDLL_LIBRARY

CONFIG += c++11

#1、(*根据自己的当前目录*)设置lib文件的生成路径
DESTDIR += ../../lib

/2、(*根据自己的当前目录*)设置dll文件的生成路径,和调用程序放同一个目录
DLLDESTDIR += ../../bin

/3、配置相应的文件名,分两个版本
CONFIG(debug, debug|release){
    TARGET = mydll_d
}else{
    TARGET = mydll
}

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    mydll.cpp

HEADERS += \
    mydll_global.h \
    mydll.h

# Default rules for deployment.
unix {
    target.path = /usr/lib
}
!isEmpty(target.path): INSTALLS += target

pro文件加了3条配置后:*.lib会生成在图中lib文件中,*.dll会生成在bin文件夹中,并且debug版和release版的名称会区别开,debug结尾多一个_d。

*同时我们将动态链接库的头文件拷贝到h文件夹内:应该有2个mydll_global.h和mydll.h文件。

4、动态库的调用

(1)显式加载动态库,也就是使用QLibrary()加载(只需要.h文件和.dll文件):

配置调用程序的pro文件,主要有以下2步:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

#1、(*根据自己的当前目录*)设置可执行程序的生成目录
DESTDIR += ../../bin

#2、(*根据自己的当前目录*)设置包含路径
INCLUDEPATH += ../../h

#3、(*根据自己的当前目录*)设置调用库路径
#LIBS += ../../lib/mydll_d.lib


# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    mainwindow.cpp

HEADERS += \
    mainwindow.h

FORMS += \
    mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

这样配置完后,*.exe调用程序会生成在bin文件夹内。

调用程序:

#include "mainwindow.h"

#include 
#include "mydll.h"       //包含动态库的头文件
#include 
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();


    /显式调用动态库

    QLibrary lib("mydll_d.dll");

    if(lib.load()){

        typedef baseClass*(*GetObject)();
        typedef void(*ReleaseObject)(baseClass* pdll);

        GetObject getobject = (GetObject)lib.resolve("getDllObject");
        ReleaseObject releaseobject = (ReleaseObject)lib.resolve("releseDllObject");

        if(getobject && releaseobject)
        {
            baseClass* pdll = getobject();
            int n = pdll->add(4, 6);
            QMessageBox::information(nullptr, "调用结果", QString::number(n));
            releaseobject(pdll);
        }
        else{
            QMessageBox::information(nullptr, "调用结果", "failed...");
        }

        lib.unload();
    }

    return a.exec();
}

结果成功:

QT-动态链接库动态加载和静态加载方法详解_第2张图片

(2)动态链接库的隐式调用(需要*.h,*.dll,*.lib三个文件):

首先将调用程序的pro文件中的第3个注释的配置项放开。

进行如下隐式调用:

#include "mainwindow.h"

#include 
#include "mydll.h"
#include 
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    /隐式调用动态库
    Mydll mydll;
    int m = mydll.add(3, 4);
    QMessageBox::information(nullptr, "调用结果", QString::number(m));

    return a.exec();
}

QT-动态链接库动态加载和静态加载方法详解_第3张图片

附:如果我们只是隐式调用的话,动态链接库文件中的基类和类外的那两个函数可以是不需要的,下面:

//显示调用动态库时需要使用使用
class  baseClass
{
public:
    baseClass();
    virtual ~baseClass();
    virtual int add(int a, int b) = 0;
};

//显示调用动态库时需要使用使用
extern "C"{
    MYDLL_EXPORT baseClass* getDllObject(); //获取类Dll的对象
    MYDLL_EXPORT void releseDllObject(baseClass* pdll); //删除类Dll的对象
}

 

你可能感兴趣的:(QT-动态链接库动态加载和静态加载方法详解)