【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中的使用相同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郑同学的笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值