IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> Qt 静态库和动态库 -> 正文阅读

[C++知识库]Qt 静态库和动态库

创建和使用静态库

创建静态库

1.选择新建文件和项目。=>选择C++ Library
在这里插入图片描述
2.进入界面
类型选择:静态库
在这里插入图片描述
项目的名字和类的名字根据自己的实际的情况修改就行。

静态库项目可以使用MinGW或MSVC编译器编译,但是项目编译生成的文件与使用的编译器有关。若使用MSVC编译,编译后会生成一个库文件.lib;若使用MinGW编译,编译后会生成一个库文件.a。

然后根据自己需要选择编译成debug版本和release版本的静态库文件。

看一下.pro文件的内容:
TEMPLATE=lib 定义项目模板是库,而不是应用程序。
CONFIG += staticlib 配置项目为静态库。
TARGET = myStaticLib定义项目编译后生成的目标文件名称是myStaticLib。

使用静态库的文件

在自己的项目中,增加库就行。
1.选择外部库
在这里插入图片描述
2.把自己编译好的动态库增加到自己的项目的include的文件夹下面。包括头文件.h和动态库文件.lib。
选择静态库文件,选择自己的静态库的路径增加进去。
在这里插入图片描述
最后可以在.pro文件中看到,自动帮助我们增加了路径


win32:CONFIG(release, debug|release): LIBS += -L$$PWD/include/ -lmyStaticLibd
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/include/ -lmyStaticLibd

INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/include/libmyStaticLibd.a
else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/include/libmyStaticLibd.a
else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$PWD/include/myStaticLibd.lib
else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$PWD/include/myStaticLibd.lib

注意:
如果你的静态的版本库与你现在项目的编译的编译器类型不同,或者编译的位数不同,会出现无法解析的外部符号。

创建和使用动态库

创建动态库

1.选择新建文件和项目。=>选择C++ Library
在这里插入图片描述
2.进入界面
类型选择:动态库
在这里插入图片描述
项目的名字和类的名字根据自己的实际的情况修改就行。

进去之后会发现我们的项目会多一个_global.h的文件
查看一下内容:

#ifndef DLL_GLOBAL_H
#define DLL_GLOBAL_H

#include <QtCore/qglobal.h>

#if defined(DLL_LIBRARY)
#  define DLL_EXPORT Q_DECL_EXPORT
#else
#  define DLL_EXPORT Q_DECL_IMPORT
#endif

#endif // DLL_GLOBAL_H

这里定义了符号DLL_EXPORT用于替代Qt的宏Q_DECL_EXPORT或Q_DECL_IMPORT。

可以到符号DLL_EXPORT,就是我们开始给起的项目的名字,我们需要在我们需要输出的地方使用这个宏来输出可以使用的对象。比如一个类,一个函数等。

注意:有时候我们看到文件输出了.dll,但是没有文件.lib,就是没有使用这个宏去输出我们的文件。

一个共享库导出给用户使用的类、符号、函数等都需要用宏Q_DECL_EXPORT来定义导出,一个使用共享库的应用程序需要通过Q_DECL_IMPORT导入共享库里的可用对象。

再看一下.pro文件:

Qt   += widgets
TARGET = mySharedLib		//生成的动态库的名字
TEMPLATE = lib				//库

DEFINES += MYSHAREDLIB_LIBRARY

目的文件准备好之后就可以编译生成DLL文件,根据使用的编译器不同,生成的文件有些区别。

若使用MSVC编译,编译后会生成.dll和.lib两个文件,.dll在运行应用程序时调用,.lib在应用程序隐式调用动态链接库时使用。
若使用MinGW编译,编译后会生成.dll和.a两个文件,.dll在运行应用程序时调用,.a在应用程序隐式调用动态链接库时使用。

使用动态库

两种调用方式:隐式链接(implicit linking)调用和显式链接(explicit linking)调用。

隐式链接调用是在编译应用程序时,有动态库的lib文件(或.a文件)和h头文件,知道DLL中有哪些接口类和函数,编译时就隐式地生成必要的链接信息,使用DLL中的类或函数时根据h头文件中的定义使用即可。应用程序运行时将自动加载DLL文件。隐式链接调用主要用于同一种编程软件(如Qt)生成的代码的共享。

显式链接调用是只有DLL文件,知道DLL里的函数原型,使用QLibrary类对象在应用程序里动态加载DLL文件,声明函数原型,并使用DLL里的函数。这种方式需要在应用程序里声明函数原型,并解析DLL里的函数。

隐式链接调用共享库

需要准备.h文件,_global.h文件,.lib文件。放到项目的include目录下。
然后增加库,跟静态的增加库是一样的。然后把.dll,文件放到程序的运行的位置就可以了。

查看一下.pro文件:
已经链接好.lib文件了

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/include/ -lmySharedLib
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/include/ -lmySharedLibd

INCLUDEPATH += $$PWD/include
DEPENDPATH += $$PWD/include

显示调用

说白了,就是只有有动态库.dll文件,和知道动态库中有什么函数,那么使用的时候,就能够直接调用动态库的文件,就是不需要连接什么。

显式链接调用共享库是通过QLibrary类实现的。QLibrary是与平台无关的,用于在运行时载入共享库,一个QLibrary对象只对一个共享库进行操作。

一般在QLibrary的构造函数中传递一个文件名,可以是带路径的绝对文件名,也可以是不带后缀的单独文件名。QLibrary会根据运行的平台自动查找不同后缀的共享库文件,例如Unix上是“.so”,Mac上是“.dylib”,Windows上是“.dll”。

例如简单调用

void MainWindow::on_pushButton_clicked()
{
   QLibrary myLib("DelphiDLL");//加载动态库文件
   if (myLib.isLoaded())
     QMessageBox::information(this,"信息","DelphiDLL.DLL已经被载入,第1处");
   typedef int (*FunDef)(int); 
   FunDef myTriple = (FunDef) myLib.resolve("triple"); //解析DLL中的函数
   int V=myTriple(ui->spinInput->value()); //调用函数
   ui->spinOutput->setValue(V);
   if (myLib.isLoaded())
     QMessageBox::information(this,"信息","DelphiDLL.DLL已经被载入,第2处");
}

QLibrary有几个函数用于DLL文件的载入与卸载:load()用于手动载入DLL文件到内存里,一般无需手工调用此函数,在DLL里的函数第一次被使用时QLibrary会自动调用此函数;isLoaded()用于判断DLL是否已经被载入内存;unload()用于将DLL从内存中卸载。

一个动态链接库在内存里只能有一个实例,也就是即使有多处调用了这个动态链接库里的函数,它也只会被载入一次,如果不是所有的实例都使用unload()卸载它,那么它会在应用程序退出时才卸载。

显式调用动态链接库里的函数,需要声明函数原型的类型,即:

typedef int (*FunDef)(int);
然后使用QLibrary的resolve()函数解析需要调用的函数。

FunDef myTriple = (FunDef) myLib.resolve(“triple”);
这样就定义了一个函数myTriple,用于实现DLL文件里的函数"triple"的功能,当然重新声明的函数名称可以和DLL里的函数名称完全相同。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-02-28 15:10:05  更:2022-02-28 15:14:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:53:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码