Qt在Windows平台上引用静态库和共享库

0x00 Qt Creator创建共享库(动态库)项目

 

// DllSelectSort01_global.h
#ifndef DLLSELECTSORT01_GLOBAL_H
#define DLLSELECTSORT01_GLOBAL_H

#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#  define Q_DECL_EXPORT __declspec(dllexport)
#  define Q_DECL_IMPORT __declspec(dllimport)
#else
#  define Q_DECL_EXPORT     __attribute__((visibility("default")))
#  define Q_DECL_IMPORT     __attribute__((visibility("default")))
#endif

#if defined(DLLSELECTSORT01_LIBRARY)
#  define DLLSELECTSORT01_EXPORT Q_DECL_EXPORT
#else
#  define DLLSELECTSORT01_EXPORT Q_DECL_IMPORT
#endif

#endif // DLLSELECTSORT01_GLOBAL_H


// dllselectsort01.h
#ifndef DLLSELECTSORT01_H
#define DLLSELECTSORT01_H

#include "DllSelectSort01_global.h"

/*
class DLLSELECTSORT01_EXPORT DllSelectSort01
{
public:
    DllSelectSort01();
};
*/

void selectSort(int* arr, int n);

#endif // DLLSELECTSORT01_H



//  dllselectsort01.cpp
#include "dllselectsort01.h"
/*
DllSelectSort01::DllSelectSort01()
{
}
*/
void selectSort(int* arr, int n){
    for(int i = 0; i < n - 1; i++)
    {
        for(int j = i + 1; j < n; j++)
        {
            if(arr[i] > arr[j])
            {
                arr[i] ^= arr[j];
                arr[j] ^= arr[i];
                arr[i] ^= arr[j];
            }
        }
    }
}

  •  构建动态库时,生成了2个可以加载动态库的文件,一个扩展名为 .a 文件,一个扩展名为 .dll 文件,.a 文件其实是动态库的引导文件

 说明:mingw编译器在Windows平台构建动态库时生成的动态库文件为.dll文件,.a文件为动态库的引导文件,可用此文件来加载动态库,这与MSVC编译器不同,MSVC编译器在构建动态库时生成的是.dll文件和.lib文件。

 

0x01 方式一:隐式调用动态库,即利用构建动态库时生成的静态库文件作为引导去调用动态库

 

#include <QCoreApplication>
#include "dllselectsort01.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int arr[] = {2020, 10, 9, 1992, 3 ,1994, 4, 16, 520, 6666};
    selectSort(arr, sizeof(arr) / sizeof(*arr));

    for(int i = 0; i < sizeof(arr) / sizeof(*arr); i++)
    {
        printf("%d ", arr[i]);
    }

    return a.exec();
}

 

  •  1. 在CallDll01.pro文件,包含需要引入动态库的头文件路径,以及引导加载动态库的静态库文件所在的路径

  •  2. 将动态库.dll文件放到可执行程序所在的目录下

0x02 方式二:显示调用动态库 ,利用QLibrary类加载动态库

  •  1. 显示调用动态库,在建立动态库时,把需要调用的函数或者类需要添加导出修饰语,其构建动态库的方式和隐式调用动态库所构建动态库的方式一样

// DllSelectSort02_global.h
#ifndef DLLSELECTSORT02_GLOBAL_H
#define DLLSELECTSORT02_GLOBAL_H

#if defined(_MSC_VER) || defined(WIN64) || defined(_WIN64) || defined(__WIN64__) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#  define Q_DECL_EXPORT __declspec(dllexport)
#  define Q_DECL_IMPORT __declspec(dllimport)
#else
#  define Q_DECL_EXPORT     __attribute__((visibility("default")))
#  define Q_DECL_IMPORT     __attribute__((visibility("default")))
#endif

#if defined(DLLSELECTSORT02_LIBRARY)
#  define DLLSELECTSORT02_EXPORT Q_DECL_EXPORT
#else
#  define DLLSELECTSORT02_EXPORT Q_DECL_IMPORT
#endif

#endif // DLLSELECTSORT02_GLOBAL_H


// dllselectsort02.h
#ifndef DLLSELECTSORT02_H
#define DLLSELECTSORT02_H

#include "DllSelectSort02_global.h"

//导出类
class DLLSELECTSORT02_EXPORT DllSelectSort02
{
public:
    DllSelectSort02();
};

//导出函数
extern "C" DLLSELECTSORT02_EXPORT void selectSort(int* arr, int n);

#endif // DLLSELECTSORT02_H

// dllselectsort02.cpp
#include "dllselectsort02.h"

DllSelectSort02::DllSelectSort02()
{
}

void selectSort(int* arr, int n){
    for(int i = 0; i < n - 1; i++)
    {
        for(int j = i + 1; j < n; j++)
        {
            if(arr[i] > arr[j])
            {
                arr[i] ^= arr[j];
                arr[j] ^= arr[i];
                arr[i] ^= arr[j];
            }
        }
    }
}
 

 

  •  2. 显示加载动态库的代码

#include <QCoreApplication>
#include <QLibrary>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    //函数指针
    typedef void(*selectSortFunc)(int arr[], int n);

    QLibrary dll("./DllSelectSort02.dll");
    if(dll.load()){
        qDebug() << "动态库加载成功!";
    }
    int arr[] = {2020, 10, 9, 1992, 3 ,1994, 4, 16, 520, 6666};

    selectSortFunc selectSort = (selectSortFunc)dll.resolve("selectSort");

    if(selectSort){
        qDebug() << "函数加载成功!";
        selectSort(arr, sizeof(arr) / sizeof(*arr));
    }else{
        qDebug() << "函数加载失败!!!";
    }

    for(int i = 0; i < sizeof(arr) / sizeof(*arr); i++){
        printf("%d ", arr[i]);
    }

    return a.exec();
}
  •  3. 把动态库放到应用程序所在的目录

 0x03 调用静态库

  • 1. 构建静态库

// aselectsort.h
#ifndef ASELECTSORT_H
#define ASELECTSORT_H

/*
class ASelectSort
{
public:
    ASelectSort();
};
*/

void selectSort(int* arr, int n);

#endif // ASELECTSORT_H


// aselectsort.cpp
#include "aselectsort.h"
/*
ASelectSort::ASelectSort()
{
}
*/
void selectSort(int* arr, int n){
    for(int i = 0; i < n - 1; i++)
    {
        for(int j = i + 1; j < n; j++)
        {
            if(arr[i] > arr[j])
            {
                arr[i] ^= arr[j];
                arr[j] ^= arr[i];
                arr[i] ^= arr[j];
            }
        }
    }
}
  •  2. APP调用静态库的工程目录结构

  •  3. 在CallA.pro文件,即APP的项目文件中中,引入需要调用静态库所在的路径,以及库的头文件所在的目录 

  •  4. 代码如下
#include <QCoreApplication>
#include "aselectsort.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    int arr[] = {2020, 10, 9, 1992, 3 ,1994, 4, 16, 520, 6666};
    selectSort(arr, sizeof(arr) / sizeof(*arr));

    for(int i = 0; i < sizeof(arr) / sizeof(*arr); i++)
    {
        printf("%d ", arr[i]);
    }

    return a.exec();
}

总结:APP在调用静态库和隐式调用动态库时,都需要在项目的工程文件(即.pro文件)中包含引入的静态库以及该库的头文件所在的路径,而显示调用动态库时则不需要;但是显示调用动态库时要在使用的类或者函数前面添加导出修饰语句,这样才能被Qt中的QLibrary::resolve()函数调用;无论显示调用还是隐式调用动态库,都需要把动态库放到APP所在的路径下,这是因为APP在运行的时候需要加载动态库,而静态库是被编译到APP中去的,所以调用动态库所生成的应用程序的占用磁盘空间的大小比调用静态库所生成的应用程序占用磁盘的大小要小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

晓琴儿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值