Qt 调用动态库 插件
来源:互联网 发布:全国软件开发人员 编辑:程序博客网 时间:2024/06/05 07:54
文章来源:http://blog.csdn.net/tujiaw/article/details/37989519
1.隐式调用
1>新建一个C++库,工程名为Cal,自动生成三个文件cal.h, cal_global.h, cal.cpp,编译后生成我们需要的Cal.lib, Cal.dll
- #ifndef CAL_H
- #define CAL_H
- #include "cal_global.h"
- class CALSHARED_EXPORT Cal
- {
- public:
- Cal();
- int add(int a, int b);
- int substract(int a, int b);
- };
- #endif // CAL_H
- #include "cal.h"
- Cal::Cal()
- {
- }
- int Cal::add(int a, int b)
- {
- return a + b;
- }
- int Cal::substract(int a, int b)
- {
- return a - b;
- }
在CalTest.pro文件所在目录下新建一个lib->cal目录,将cal相关文件拷贝到这个目录下:cal.h, cal_global.h, Cal.lib;
在CalTest.pro文件后面增加两行代码:
INCLUDEPATH += $${PWD}/lib/cal
LIBS += $${PWD}/lib/cal/Cal.lib
我们在构造函数里面测试,代码如下:
- #include "dialog.h"
- #include "ui_dialog.h"
- #include "cal.h"
- #include <QDebug>
- Dialog::Dialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::Dialog)
- {
- ui->setupUi(this);
- Cal cal;
- int a = 100, b = 200;
- int addResult = cal.add(a, b);
- int substractResult = cal.substract(a, b);
- qDebug() << "add:" << addResult << ",substract:" << substractResult;
- }
- Dialog::~Dialog()
- {
- delete ui;
- }
编译完成之后,将Cal.dll文件拷贝到生成的CalTest.exe目录下运行即可。
隐式调用用起来比较方便,但是不太灵活,如果缺少头文件,库文件那么这个程序就编译,执行不了了。
2.显示调用
Cal工程代码如下:
- #ifndef CAL_H
- #define CAL_H
- #include "cal_global.h"
- class CALSHARED_EXPORT Cal
- {
- public:
- Cal();
- int add(int a, int b);
- int substract(int a, int b);
- };
- extern "C" CALSHARED_EXPORT Cal* createCal();
- extern "C" CALSHARED_EXPORT void deleteCal(Cal *cal);
- #endif // CAL_H
- #include "cal.h"
- Cal::Cal()
- {
- }
- int Cal::add(int a, int b)
- {
- return a + b;
- }
- int Cal::substract(int a, int b)
- {
- return a - b;
- }
- Cal* createCal()
- {
- return new Cal();
- }
- void deleteCal(Cal *cal)
- {
- delete cal;
- cal = NULL;
- }
CalTest调用的时候,CalTest.pro里就不需要
INCLUDEPATH += $${PWD}/lib/cal
LIBS += $${PWD}/lib/cal/Cal.lib
这两行代码了,直接看cpp文件
- #include "dialog.h"
- #include "ui_dialog.h"
- #include <QDebug>
- #include <QLibrary>
- #include "../Cal/cal.h"
- Dialog::Dialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::Dialog)
- {
- ui->setupUi(this);
- typedef Cal* (*CreateCal)();
- typedef void (*DeleteCal)(Cal *cal);
- QLibrary lib("Cal.dll");
- if (lib.load()) {
- CreateCal createCal = (CreateCal)lib.resolve("createCal");
- DeleteCal deleteCal = (DeleteCal)lib.resolve("deleteCal");
- if (createCal && deleteCal) {
- Cal *pcal = createCal();
- int a = 100, b = 200;
- int addResult = pcal->add(a, b);
- int substractResult = pcal->substract(a, b);
- qDebug() << "add:" << addResult << ",substract:" << substractResult;
- deleteCal(pcal);
- } else {
- qDebug() << "resolve failed";
- }
- lib.unload();
- } else {
- qDebug() << "load failed";
- }
- }
- Dialog::~Dialog()
- {
- delete ui;
- }
#include "../Cal/cal.h"头文件还是需要的,因为我们不知道Cal类是怎么声明的。
这样当这个dll不存在的时候我们的程序还是可以通过编译运行的。
但是这里还存在问题,Cal类我们还是导出了,因为我们演示的是一个比较简单的类,如果这个类比较复杂那么导出就有麻烦了,因为导出类的父类和子类也要导出,所以我们希望这个类不导出也可以使用。
3.纯虚基类,不导出类,通过虚表来定位具体的函数
Cal工程代码
- #ifndef CALINTERFACE_H
- #define CALINTERFACE_H
- #include "cal_global.h"
- class CalInterface
- {
- public:
- virtual ~CalInterface() {}
- virtual int add(int a, int b) = 0;
- virtual int substract(int a, int b) = 0;
- };
- extern "C" CALSHARED_EXPORT CalInterface* createCal();
- extern "C" CALSHARED_EXPORT void deleteCal(CalInterface *cal);
- #endif // CALINTERFACE_H
- #include "CalInterface.h"
- #include "cal.h"
- CalInterface* createCal()
- {
- return new Cal();
- }
- void deleteCal(CalInterface *cal)
- {
- delete cal;
- cal = NULL;
- }
- #ifndef CAL_H
- #define CAL_H
- #include "cal_global.h"
- #include "CalInterface.h"
- class Cal : public CalInterface
- {
- public:
- Cal();
- virtual ~Cal();
- virtual int add(int a, int b);
- virtual int substract(int a, int b);
- };
- #endif // CAL_H
CalTest工程调用:
- #include "dialog.h"
- #include "ui_dialog.h"
- #include <QDebug>
- #include <QLibrary>
- #include "../Cal/CalInterface.h"
- Dialog::Dialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::Dialog)
- {
- ui->setupUi(this);
- typedef CalInterface* (*CreateCal)();
- typedef void (*DeleteCal)(CalInterface *cal);
- QLibrary lib("Cal.dll");
- if (lib.load()) {
- CreateCal createCal = (CreateCal)lib.resolve("createCal");
- DeleteCal deleteCal = (DeleteCal)lib.resolve("deleteCal");
- if (createCal && deleteCal) {
- CalInterface *pcal = createCal();
- int a = 100, b = 200;
- int addResult = pcal->add(a, b);
- int substractResult = pcal->substract(a, b);
- qDebug() << "add:" << addResult << ",substract:" << substractResult;
- deleteCal(pcal);
- } else {
- qDebug() << "resolve failed";
- }
- lib.unload();
- } else {
- qDebug() << "load failed";
- }
- }
- Dialog::~Dialog()
- {
- delete ui;
- }
这样Cal类就不必要导出了,而且CalInterface.h头文件是比较独立的,不依赖于其他的一些东西。
C++调用方法跟这类似,只是将QLibrary换成了LoadLibrary,GetProcAddress。
4.插件编写(lower-level api)
1>创建C++库,类型选择Qt Plugin,名称CalPlugin,删掉自动生成的genericplugin.h和genericplugin.cpp两个文件
2>创建接口类头文件calinterface.h
- #ifndef CALINTERFACE_H
- #define CALINTERFACE_H
- #include <QtPlugin>
- class CalInterface
- {
- public:
- virtual ~CalInterface() {}
- virtual int add(int a, int b) = 0;
- virtual int substract(int a, int b) = 0;
- };
- Q_DECLARE_INTERFACE(CalInterface, "org.qt-project.Qt.Examples.CalPlugin.CalInterface")
- #endif // CALINTERFACE_H
- #ifndef CAL_H
- #define CAL_H
- #include <QObject>
- #include "calinterface.h"
- class Cal : public QObject, public CalInterface
- {
- Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.Examples.CalPlugin.Cal" FILE "CalPlugin.json")
- Q_INTERFACES(CalInterface)
- public:
- explicit Cal(QObject *parent = 0);
- int add(int a, int b);
- int substract(int a, int b);
- };
- #endif // CAL_H
- #include "cal.h"
- Cal::Cal(QObject *parent)
- : QObject(parent)
- {
- }
- int Cal::add(int a, int b)
- {
- return a + b;
- }
- int Cal::substract(int a, int b)
- {
- return a - b;
- }
5.调用插件
1>创建CalPluginTest对话框类型的应用程序,编译运行;
2>在CalPluginTest.exe所在目录下新建一个plugins子目录,将上面生成的CalPlugin.dll插件拷贝到plugins目录下;
3>直接在构造函数写测试代码如下:
- #include "dialog.h"
- #include "ui_dialog.h"
- #include <QtWidgets>
- #include "../CalPlugin/calinterface.h"
- Dialog::Dialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::Dialog)
- {
- ui->setupUi(this);
- QDir dir(QCoreApplication::applicationDirPath() + "/plugins");
- foreach (QString filename, dir.entryList(QDir::Files)) {
- qDebug() << "path:" << dir.absoluteFilePath(filename);
- QPluginLoader loader(dir.absoluteFilePath(filename));
- CalInterface *pcal = qobject_cast<CalInterface*>(loader.instance());
- if (pcal) {
- int a = 12, b = 34;
- int addResult = pcal->add(a, b);
- int substractResult = pcal->substract(a, b);
- qDebug() << "add:" << addResult << ", substract:" << substractResult;
- } else {
- qDebug() << "error";
- }
- }
- }
- Dialog::~Dialog()
- {
- delete ui;
- }
- Qt 调用动态库 插件
- C++ Qt 调用动态库 插件
- QT 4.7动态库调用
- QT 插件调用
- Qt调用插件
- QT调用动态库的方法
- Qt 调用外部C动态库
- QT调用动态链接库实例
- qt在Windows下调用动态库
- qt和VS动态库调用心得
- Qt .so动态链接库调用,配置
- Qt 调用CUDA动态库配置
- qt调用动态库注意点
- QT 调用动态库接口方法
- vs 2010 中用qt插件编写动态库dll
- 【转】QT怎么调用C++的动态库
- Qt中调用VC6生成的动态库DLL文件
- QT Creator中调用动态库文件例程
- Cocos2d-x3.1SpriteBatchNode使用
- Android Bitmap详细介绍
- web.xml的作用
- MySQL触发器
- android程序运行时总出现“Unfortunately,程序名 has stopped” 的问题
- Qt 调用动态库 插件
- ios 开发一些公用的头文件
- linux非管理员安装python yaml
- hduoj1171!【数学】
- MySQL 重排auto_increment值
- 关于子网掩码的理解
- 每天进步一点点——求最大子序列和问题
- 【2556】传说中的数据结构 sdutOJ
- MySQL 正则表达是的使用