本篇文章以我实际使用过程为例,在此总结一下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();
}
当程序运行时,会尝试加载动态库,加载成功就运行,失败则不运行。
这样的话可以实现一版程序,多种运行结果,是最灵活的链接方式
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我正在使用Rails构建一个简单的聊天应用程序。当用户输入url时,我希望将其输出为html链接(即“url”)。我想知道在Ruby中是否有任何库或众所周知的方法可以做到这一点。如果没有,我有一些不错的正则表达式示例代码可以使用... 最佳答案 查看auto_linkRails提供的辅助方法。这会将所有URL和电子邮件地址变成可点击的链接(htmlanchor标记)。这是文档中的代码示例。auto_link("Gotohttp://www.rubyonrails.organdsayhellotodavid@loudthinking.
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.
我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty