QT中dll的生成及使用

22 篇文章 2 订阅
本文详细介绍了C++中静态库、动态库和导入库的区别,重点讲解了静态链接与动态链接的方法,并通过QT示例展示了如何在项目中使用动态库,包括隐式加载和显式加载。
摘要由CSDN通过智能技术生成

C++中的库分为三种:静态库、动态库和导入库

1、静态库:

    静态库扩展名为.lib,静态链接(即代码会直接编译进可执行文件)。静态库是一个或多个obj文件的打包。

2、动态库和导入库

    和静态库不同,动态库不会编译进可执行文件中,多个程序引用动态库时,内存中实际只会有一份动态库的内容。
    用QT创建动态库时,实际生成两个文件,一个lib文件和一个dll文件,这个lib文件就是导入库。

    导入库是动态库的辅助库,导入库中不含代码,而是为链接程序提供信息,包含在.exe文件中建立动态链接时要用到的重定位表。

    导入库用于程序开发时,动态库用于程序运行时。

3、在项目中使用动态库的方法
1) 隐式加载

    这种方式和静态库的使用方法一样,注意此时要包含的是导入库而不是动态库,依然需要头文件,代码中可直接使用头文件中的函数名,并且这种方式在运行时需要动态库。

2) 显式加载(又称运行时动态链接):

    如果使用windows接口,则在代码中使用LoadLibrary()显式打开dll文件,使用GetProcAddress获取函数地址然后使用,使用完之后用FreeLibrary显式释放dll文件。这种方式不需要导入库及.h文件。
    在QT中则可以使用QLibrary的load方法。
    注:使用隐式加载时,如果进程在启动时未找到dll,则操作系统将终止此进程。但使用显式加载时则进程不会被终止。
    以上参考:https://blog.csdn.net/finewind/article/details/44959039
静态链接库、动态链接库、导入库的区别 - 简书

4、隐示加载dll demo

创建一个TestDll项目,创建项目的时候选择 Library->C++库

pro文件

QT       -= gui

TARGET = TestDll
TEMPLATE = lib

DEFINES += TESTDLL_LIBRARY

SOURCES += testDll.cpp

HEADERS += testdll.h\
        testdll_global.h \
    basetest.h

unix {
    target.path = /usr/lib
    INSTALLS += target
}

testDll.h

#ifndef TESTDLL_H
#define TESTDLL_H
#include "basetest.h"
#include "testdll_global.h"

class TESTDLLSHARED_EXPORT TestDll : public BaseTest
{

public:
    TestDll();

    virtual int add(int a, int b);
};

extern "C" {
    TESTDLLSHARED_EXPORT BaseTest *getObj();
}

#endif // TESTDLL_H

basetest.h

#ifndef BASETEST
#define BASETEST

class BaseTest
{

public:
    BaseTest() {}

    virtual int add(int a, int b) = 0;
};

#endif // BASETEST

testdll_global.h

#ifndef TESTDLL_GLOBAL_H
#define TESTDLL_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(TESTDLL_LIBRARY)
#  define TESTDLLSHARED_EXPORT Q_DECL_EXPORT
#else
#  define TESTDLLSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // TESTDLL_GLOBAL_H

testDll.cpp

#include "testdll.h"


TestDll::TestDll()
{
}

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

BaseTest *getObj()
{
    return new TestDll();
}

构建之后会在build同时生成一个.lib和.dll文件

image.png

TestDll.lib即为导出库

创建一个DllUser项目

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = DllUser
TEMPLATE = app


SOURCES += main.cpp\
        mainwindow.cpp

INCLUDEPATH += include

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

LIBS += lib/TestDll.lib

CONFIG(debug, debug|release){
    DESTDIR = bin/Debug
} else {
    DESTDIR = bin/Debug
}

在该工程的根目录下创建一个lib文件夹,将dll的导出库拷贝到该目录
在根目录下创建一个include文件夹,将dll的头文件拷贝到该目录
并将TestDll.dll拷贝至DllUser.exe的同级目录

image.png

mainwindow.cpp代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "include/testdll.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_clicked()
{
    int a = ui->lineEdit->text().toInt();
    int b = ui->lineEdit_2->text().toInt();

    TestDll obj;
    int sum = obj.add(a, b);
    QString str = QString::number(sum);
    ui->label->setText(str);
    ui->label->show();
}
5、显示加载dll demo

    显示加载如果只是导出一个函数比较简单,但是如果要导出一个类的话稍微有些麻烦,该demo主要演示如何从dll中导出一个类。
    首先,定义一个BaseTest抽象类作为TestDll的基类,BaseTest的头文件需要在使用Dll的项目中引用
DLL的项目代码在4中已展示
下面创建一个显示加载该dll的项目DllLoad, pro文件如下:

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = DllLoad
TEMPLATE = app

INCLUDEPATH += include


SOURCES += main.cpp\
        mainwindow.cpp

HEADERS  += mainwindow.h

FORMS    += mainwindow.ui

CONFIG(debug, debug|release){
    DESTDIR = bin/Debug
} else {
    DESTDIR = bin/Debug
}

注意需要在该项目的根目录下创建include目录,并将抽象类BaseTest的头文件basetest.h拷贝到该文件夹下,DllLoad不需要再引用dll的其他头文件
mainwindow.cpp的代码

#include <QApplication>
#include <QLibrary>
#include <QDebug>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "include/basetest.h"

typedef BaseTest* (*Get_Obj)(); //定义函数指针,以备调用
BaseTest *g_obj = NULL;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    loadDll();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::loadDll()
{
    QLibrary testLib("TestDll.dll");
    if (testLib.load()) {
        Get_Obj getObj = (Get_Obj)testLib.resolve("getObj");
        if (getObj) {
            qDebug()<<"getObj";
            g_obj = getObj();
        }
    }
}

void MainWindow::on_pushButton_clicked()
{
    int a = ui->lineEdit->text().toInt();
    int b = ui->lineEdit_2->text().toInt();

    if (g_obj) {
        int sum = g_obj->add(a, b);
        QString str = QString::number(sum);
        ui->label->setText(str);
        ui->label->show();
    }
}

将TestDll.dll拷贝至exe同级目录即可运行


/********************************************QT 生成DLL 流程

1. 先建立一个库文件

               

 

2. 自定义项目名称以及项目路径 

    

3.选择qmake

           

 

4. 选择共享库和 Qt module

          

 

        

 

5  根据需求选择相应的编译器,在这里选择 MinGW32

   

6.  点击完成;

                

 

7.  项目总览:

         

 

8.  将creatDLL_C_1__global.h头文件中的内容拷贝到creatdll_c_1.h头文件中;

        

 

9.  然后如下所示:

        

 

10. 在creatdll_c_1_.h头文件中声明加减乘除四个函数

        

 

11. 在creatdll_c_1.cpp源文件中简单实现函数的功能 

         

 

12.  项目右键, 点击qmake编译运行

    

 

13.  项目右键,点击重新构建

           

 

14. 构建成功

         

 

15.  运行项目

       

16. 忽略此弹框,编译成功,生成dll、a库文件

注意:生成的dll库文件是在项目 → build → 构建目录的debug文件夹中,查看自己构建项目时所存储的位置

      

      

  • 17
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Ubuntu使用动态链接库(DLL)的过程与Windows有所不同。在Ubuntu,动态链接库也称为共享对象(Shared Object),其文件扩展名通常为.so。在QT使用DLL主要分为以下几个步骤: 1. 定义DLL接口 在定义DLL接口时,需要使用extern "C"来告诉编译器要按照C语言的方式来导出函数。例如: ``` #ifndef MYDLL_H #define MYDLL_H #ifdef __cplusplus extern "C" { #endif void test(); #ifdef __cplusplus } #endif #endif // MYDLL_H ``` 2. 编写DLL实现代码 在Ubuntu,我们需要使用GCC编译器来编译生成.so文件。例如,我们有一个test.cpp文件实现了test()函数: ``` #include "mydll.h" #include <iostream> void test() { std::cout << "Hello World!" << std::endl; } ``` 我们可以使用以下命令来编译生成.so文件: ``` g++ -shared -fPIC -o libtest.so test.cpp ``` 3. 在QT调用DLLQT,我们可以使用QLibrary类来加载和调用DLL。例如: ``` #include <QLibrary> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QLibrary myLib("libtest.so"); if (myLib.load()) { typedef void (*TestFunc)(); TestFunc testFunc = (TestFunc)myLib.resolve("test"); if (testFunc) { testFunc(); } else { qDebug() << "Failed to resolve test function."; } } else { qDebug() << "Failed to load library."; } return a.exec(); } ``` 在以上代码,我们首先使用QLibrary类加载.so文件,然后使用resolve()函数来获取test()函数的地址,最后通过调用该函数来执行DLL的代码。 需要注意的是,编写和使用DLL需要考虑到平台相关性和兼容性问题,因此在实际开发需要仔细设计和测试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值