1、先说明本文要实现的功能:
(1)生成一个动态链接库;
(2)隐式加载动态链接库,需要的文件:*.h(非必须文件,如果不使用*.h文件,那么调用程序所需要的函数或是类就需要自己声明,所以说建议直接使用动态链接库的*.h文件。如果使用别人的动态链接库没有*.h文件那只有自己在调用程序中声明了);*.dll文件(必须有);*.lib文件(必须有)。
(3)使用QLibrary()动态加载,*.h同2;*.dll(必须有);*.lib(不使用)。
2.项目文件构成:
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();
}
结果成功:
(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();
}
附:如果我们只是隐式调用的话,动态链接库文件中的基类和类外的那两个函数可以是不需要的,下面:
//显示调用动态库时需要使用使用
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的对象
}