【Qt教程18】Qt Creator动态库(MinGW和MSVC的区别)
原创作者:郑同学的笔记
原创地址:https://zhengjunxue.blog.csdn.net/article/details/138708816
qq技术交流群:921273910
一、MSVC生成动态库、使用动态库
1、生成动态库
-
1.1、dll_demo_msvc_global.h——导入导出
-
1.2、cpp
-
1.3、pro文件
-
1.4、编译
2、使用动态库(测试进程和dll都使用相同编译器MSVC)——隐式调用(编译时就链接)
-
2.1、项目依赖
-
2.2、调用动态库的代码
-
2.3、pro文件
#-------------------------------------------------
#
# Project created by QtCreator 2024-05-11T10:11:59
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = testProcess
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as 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 you use 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
CONFIG += c++11
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
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../build-dll_Demo_MSVC-Desktop_Qt_5_12_0_MSVC2017_64bit-Debug/release/ -ldll_Demo_MSVC
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../build-dll_Demo_MSVC-Desktop_Qt_5_12_0_MSVC2017_64bit-Debug/debug/ -ldll_Demo_MSVC
else:unix: LIBS += -L$$PWD/../build-dll_Demo_MSVC-Desktop_Qt_5_12_0_MSVC2017_64bit-Debug/ -ldll_Demo_MSVC
INCLUDEPATH += $$PWD/../dll_Demo_MSVC
DEPENDPATH += $$PWD/../dll_Demo_MSVC
- 2.4、编译测试进程
- 2.5、把动态库拷贝到测试进程目录下,运行
程序输出
- 2.6、如果不把动态库拷贝到进程目录下,会报错如下
通过Qt Creator运行,报错如下
点击testProcess.exe运行,报错如下
3、使用动态库——显式调用(动态加载)
- 用法
- 3.1、dll库的头文件
#ifndef DLL_DEMO_MSVC_H
#define DLL_DEMO_MSVC_H
#include "dll_demo_msvc_global.h"
class DLL_DEMO_MSVCSHARED_EXPORT Dll_Demo_MSVC
{
public:
Dll_Demo_MSVC();
//static Dll_Demo_MSVC* createInstance(); // 添加一个静态函数用于创建类的实例
};
#endif // DLL_DEMO_MSVC_H
- 3.2、dll库的cpp
#include "dll_demo_msvc.h"
#include <QDebug>
Dll_Demo_MSVC::Dll_Demo_MSVC()
{
qDebug()<<"i am dll by MSVC,dll_Demo_MSVC";
}
//Dll_Demo_MSVC* Dll_Demo_MSVC::createInstance()
//{
// return new Dll_Demo_MSVC();
//}
extern "C" DLL_DEMO_MSVCSHARED_EXPORT Dll_Demo_MSVC* createInstance()
{
return new Dll_Demo_MSVC();
}
- 3.3、如何使用dll
#include "mainwindow.h"
#include <QApplication>
#include <QLibrary>
#include <QDebug>
#include <QDir>
#include "../dll_Demo_MSVC/dll_demo_msvc.h"
// 定义创建类实例的函数指针类型
typedef Dll_Demo_MSVC* (*CreateInstanceFunction)();
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
// 加载动态链接库
// QLibrary library("../../build-dll_Demo_MSVC-Desktop_Qt_5_12_0_MSVC2017_64bit-Debug/debug/dll_Demo_MSVC.dll"); // 替换成你的动态链接库的路径
// 获取动态链接库文件的绝对路径
QDir dir(QCoreApplication::applicationDirPath());
QString dllPath = dir.absoluteFilePath("../../build-dll_Demo_MSVC-Desktop_Qt_5_12_0_MSVC2017_64bit-Debug/debug/dll_Demo_MSVC.dll");
// 加载动态链接库
QLibrary library(dllPath);
if (library.load()) {
qDebug() << "Library loaded successfully!";
// 获取动态链接库中的创建类实例的函数指针
CreateInstanceFunction createInstance = (CreateInstanceFunction)library.resolve("createInstance");
if (createInstance) {
// 创建类的实例
Dll_Demo_MSVC* demoInstance = createInstance();
// 调用实例化的类的成员函数
// demoInstance->sayHelloInstance();
// 释放类的实例
delete demoInstance;
} else {
qDebug() << "Failed to resolve function createInstance()";
}
// 卸载动态链接库
library.unload();
} else {
// qDebug() << "Failed to load library!";
qDebug() << "Failed to load library! Error: " << library.errorString();
}
return a.exec();
}
- 3.4、编译输出
4、显示调用中如果没有extern "C"
,会发生什么
答:没有extern "C"
,以下流程会报错
// 获取动态链接库中的创建类实例的函数指针
CreateInstanceFunction createInstance = (CreateInstanceFunction)library.resolve("createInstance");
原因:简单来说,就是c++编译时,会对名字进行修饰,修饰完名字就不叫createInstance
了。详细的原因,可以查看我之前写的两篇文章
【cmake实战六】如何使用编译的库(动态库dll)——windows系统
【编译、链接、装载八】链接
二、MinGW生成动态库、使用动态库(测试进程和库都是以MinGW)
1、生成动态库
2、使用动态库——编译时链接——隐式调用
- 同 一、MSVC中的使用相同
3、使用动态库——运行时链接——显示调用
- 同 一、MSVC中的使用相同