本篇文章以我实际使用过程为例,在此总结一下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();

    }

当程序运行时,会尝试加载动态库,加载成功就运行,失败则不运行。
这样的话可以实现一版程序,多种运行结果,是最灵活的链接方式