本篇文章以我实际使用过程为例,在此总结一下qt链接动态库的几种方式
使用的动态库为libzint.so,库目录为/usr/local/lib
静态链接
第一种为直接将库添加到QT中,可以看成静态库
通过pro文件添加链接
//demo.pro
LIBS += -L/usr/local/lib/ -lzint
在用到外部库的程序代码中直接
//mainwindow.cpp
#include <zint.h>
这样就可以直接调用外部库的中结构体与函数接口
//mainwindow.cpp
//图片存储路径
QString strImagePath = QCoreApplication::applicationDirPath() + "/barcode.bmp";
//设置生成属性,可根据需要自行修改
struct zint_symbol * my_symbol = ZBarcode_Create(); //外部接口与外部结构体,直接调用就可以
my_symbol->symbology=BARCODE_QRCODE;
strcpy(my_symbol->outfile, strImagePath.toStdString().c_str());
qDebug()<<my_symbol->outfile<<endl;
QString b="1\n2\n行";
//完成二维码制作并保存
ZBarcode_Encode(my_symbol,(unsigned char*)b.toStdString().c_str(),0); //外部接口
ZBarcode_Print(my_symbol,0); //外部接口
ZBarcode_Delete(my_symbol); //外部接口
//在label上显示二维码图片
QImage img;
img.load(strImagePath.toStdString().c_str());
QImage newImg = img.scaled(ui->label->width(),ui->label->height(), Qt::IgnoreAspectRatio);
ui->label->setPixmap(QPixmap::fromImage(newImg));
可以直接使用外部库,直接调用包含的结构体与函数接口
这种方法最简单方便,但是限制条件也最多
编译与运行都需要有对应的外部库文件
但是实际应用中,一套代码对应多个版本,而库的使用也不尽相同,那么每当我用不到一个库的时候,我需要删除所有与此相关的代码,这无疑是项十分繁琐浪费资源的事情。
那么下面我们来看条件编译。
静态链接(条件编译)
既然我要控制库的使用与否,那我在静态链接的情况下,我必须从头控制,即在pro文件中,编译时是否链接外部库的时候进行控制。
//demo.pro
DEFINES += USE_ZINT
USE_ZINT{
message('USE ZINT')
LIBS+=-L/usr/local/lib -lzint
}else{
message('NO USE ZINT')
}
//mainwindow.cpp
#ifdef USE_ZINT
#include <zint.h>
#endif
//mainwindow.cpp
#ifdef USE_ZINT
//图片存储路径
QString strImagePath = QCoreApplication::applicationDirPath() + "/barcode.bmp";
//设置生成属性,可根据需要自行修改
struct zint_symbol * my_symbol = ZBarcode_Create(); //外部接口与外部结构体
my_symbol->symbology=BARCODE_QRCODE;
strcpy(my_symbol->outfile, strImagePath.toStdString().c_str());
qDebug()<<my_symbol->outfile<<endl;
QString b="1\n2\n行";
//完成二维码制作并保存
ZBarcode_Encode(my_symbol,(unsigned char*)b.toStdString().c_str(),0); //外部接口
ZBarcode_Print(my_symbol,0); //外部接口
ZBarcode_Delete(my_symbol); //外部接口
//在label上显示二维码图片
QImage img;
img.load(strImagePath.toStdString().c_str());
QImage newImg = img.scaled(ui->label->width(),ui->label->height(), Qt::IgnoreAspectRatio);
ui->label->setPixmap(QPixmap::fromImage(newImg));
#endif
//这种方法可以方便的设置,使用与否此库
DEFINES += USE_ZINT //使用此库,定义USE_ZINT
#DEFINES += USE_ZINT //不使用此库,#注释掉,则后面不执行ifdef中的语句
通过一行代码可以控制程序实现两个版本,使用该库,不使用该库。
相较于纯静态链接,更加的灵活的实现控制,不用再去一行行的删除代码。
上述的两种的静态链接,都需要在编译和运行时,具有库的环境。
编译时需要找到库读取头文件,运行时也需要找到库读取头文件。
对于多人协作完成项目,会更加的繁琐,因为需要每个人都拥有每个库的编译环境,才能完整的编译完成整个程序
这时候就体现出动态加载的优点了,编译时不必需要库的环境,只有运行时需要。
动态加载
动态加载的编写更加繁琐,也借助了QLibrary才能实现
因为编译过程不需要库环境,所以不用修改pro文件,直接修改需要该库的程序文件
QLibrary使用过程简单来说就是先加载动态库文件,然后读取外部动态库接口。
调用load()来加载动态库文件,resolve()用于解析库中的符号,读取函数接口。
首先添加
//mainwindow.cpp
#include <QLibrary>
那么接下来我们就可以通过QLibrary来使用外部库了
//mainwindow.cpp
//定义程序中的承载函数
typedef zint_symbol *(*Zint_Create)();
typedef void (*Zint_Delete)(struct zint_symbol *symbol);
typedef int (*Zint_Encode)(struct zint_symbol *symbol, const unsigned char *source, int length);
typedef int (*Zint_Print)(struct zint_symbol *symbol, int rotate_angle);
//加载动态库
QLibrary* mainFunDll = new QLibrary("/usr/local/lib/libzint.so.2.11");
if (mainFunDll->load()) //若加载成功,则启用二维码
{
qDebug()<<"-------启用zint二维码库------"<<endl;
QString strImagePath = QCoreApplication::applicationDirPath() + "/barcode.bmp";
//读取外部动态库接口
Zint_Create creat=(Zint_Create)mainFunDll->resolve("ZBarcode_Create");
Zint_Encode encode=(Zint_Encode)mainFunDll->resolve("ZBarcode_Encode");
Zint_Print print=(Zint_Print)mainFunDll->resolve("ZBarcode_Print");
Zint_Delete Delete=(Zint_Delete)mainFunDll->resolve("ZBarcode_Delete");
struct zint_symbol * my_symbol = (zint_symbol *)creat();
my_symbol->symbology=BARCODE_QRCODE;
strcpy(my_symbol->outfile, strImagePath.toStdString().c_str());
QString b="1\n2\n行";
//生成二维码
encode(my_symbol,(unsigned char*)b.toStdString().c_str(),0);
print(my_symbol,0);
Delete(my_symbol);
//在label上显示二维码图片
QImage img;
img.load(strImagePath.toStdString().c_str());
QImage newImg = img.scaled(ui->label_QR->width(),ui->label_QR->height(), Qt::IgnoreAspectRatio);
ui->label_QR->setPixmap(QPixmap::fromImage(newImg));
}
else //加载失败则不启用
{
qDebug()<<"-------不启用zint二维码库------"<<endl;
ui->label_QR->clear();
}
当程序运行时,会尝试加载动态库,加载成功就运行,失败则不运行。
这样的话可以实现一版程序,多种运行结果,是最灵活的链接方式