Qt DLL总结【二】-创建及调用QT的 DLL
目录
Qt DLL总结【一】-链接库预备知识
Qt DLL总结【二】-创建及调用QT的 DLL
Qt DLL总结【三】-VS2008+Qt 使用QPluginLoader访问DLL
开发环境:VS2008+Qt4.7.4
最近看了不少Qt的DLL例子,总结一下如何创建和调用QT 动态链接库。
先讲一下对QT动态链接库的调用方法,主要包括:
1、显式链接DLL,调用DLL的全局函数,采用Qt的QLibrary方法
2、显示链接DLL,调用DLL中类对象、成员函数。(通过对象即可实现类成员函数的调用)
①用虚函数表的方法,这也是COM使用的方法,利用Qt的QLibrary技术调用;
②用GetProcAddress直接调用。
③用Qt的QPluginLoader类直接调用生成的DLL插件类对象
3、隐式链接DLL:也是采用Qt的Qlibrary方法
关于这种三种方法,下面详细叙说
详细分类叙述
前提:两个项目文件目录
1、TestDLL项目:testdll_global.h,TestDll.h,TestDll.cpp
2、TestMain exe应用项目:main.cpp
testdll_global.h 文件源代码一直不变
#ifndef TESTDLL_GLOBAL_H
#define TESTDLL_GLOBAL_H#include <QtCore/qglobal.h>#ifdef TESTDLL_LIB
# define TESTDLL_EXPORT Q_DECL_EXPORT
#else
# define TESTDLL_EXPORT Q_DECL_IMPORT
#endif#endif // TESTDLL_GLOBAL_H
DLL的显式链接在某些时候比隐式链接具有更大的灵活性。比如,如果在运行时发现DLL无法找到,程序可以显示一个错误信息并能继续运行。当你想为你的程序提供插件服务时,显式链接也很有用处
1、采用显示链接,调用DLL中全局函数,只需要一个TestDLL.dll。
通常Windows下程序显示调用dll的步骤分为三步(三个函数):LoadLibrary()、GetProcAdress()、FreeLibrary()
其中,LoadLibrary() 函数用来载入指定的dll文件,加载到调用程序的内存中(DLL没有自己的内存!)
GetProcAddress() 函数检索指定的动态链接库(DLL)中的输出库函数地址,以备调用
FreeLibrary() 释放dll所占空间
而QT的QLibrary类显示链接调用DLL的步骤:load()、resolve(const char * symbol )、unload()和VC步骤类似
TestDll.dll项目中的TestDLL.h源码
#ifndef TESTDLL_H
#define TESTDLL_H#include "testdll_global.h"class TESTDLL_EXPORT TestDll
{
public:TestDll();~TestDll();
private:};
extern "C" TESTDLL_EXPORT void helloWorld();
extern "C" TESTDLL_EXPORT int add(int a,int b);
#endif // TESTDLL_H
TestDll.dll项目中的TestDLL.cpp源码
#include <iostream>
#include "TestDll.h"TestDll::TestDll()
{}TestDll::~TestDll()
{}void helloWorld()
{std::cout << "hello,world!";
}
int add(int a,int b)
{return a + b;
}
注:1)建立成功DLL项目后,可以在VS命令提示行中用命令"dumpbin -exports DllTest.dll"来查看(也可以用VC工具包中的depends使用程序来查看)
注:2)必须使用extern "C"链接标记,否则C++编译器会产生一个修饰过的函数名,这样导出函数的名字将不再是helloworld,而是一个形如" ?helloWorld@TestDll@@UAEXXZ”的名字。为什么名字不是helloworld呢?这是因为C++为了支持函数的重载,会在编译时将函数的参数类型信息以及返回值类型信息加入到函数名中,这样代码中名字一样的重载函数,在经过编译后就互相区分开了,调用时函数名也经过同样的处理,就能找到对应的函数了。详细可以看这篇文章动态链接库(Dynamic Link Library)学习笔记
TestMain项目 main.cpp
#include <QtCore/QCoreApplication>
#include <iostream>
#include <QLibrary>typedef int (*Fun)(int,int); //定义函数指针,int add(int a,int b);
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QLibrary mylib("TestDll.dll"); //声明所用到的dll文件int result;//判断是否正确加载if (mylib.load()) {std::cout << "DLL load is OK!"<<std::endl;//调用外部函数 add()Fun add = (Fun)mylib.resolve("add"); //是否成功连接上 add() 函数if (add) {std::cout << "Link to add Function is OK!"<<std::endl;//这里函数指针调用dll中的 add() 函数result = add(5,6); std::cout << result;}elsestd::cout << "Link to add Function failed!!"<<std::endl;}//加载失败elsestd::cout << "DLL is not loaded!"<<std::endl;return a.exec();
}
2、采用显示链接,调用C++类中的类对象、成员函数
如果你想导出并显式链接一组C++类中的成员函数又该怎么办呢?这里有两个问题。第一是C++成员函数名是经过修饰的(即使指定extern "C"标记也是这样);第二是C++不允许将指向成员函数的指针转换成其它类型。这两个问题限制了C++类的显式链接。下面介绍两种方法来解决这个问题:
①用虚函数表的方法,这也是COM使用的方法,利用Qt的QLibrary技术调用;
②用GetProcAddress直接调用。
③用Qt的QPluginLoader类直接调用生成的DLL插件类对象
①虚函数表的方法,QLibrary 技术调用
TestDll.h代码
#ifndef TESTDLL_H
#define TESTDLL_H#include "testdll_global.h"class TESTDLL_EXPORT TestDll
{
public:TestDll();virtual~TestDll(); virtual void helloWorld(); //类成员函数
private:};
extern "C" TESTDLL_EXPORT TestDll* getTestDll(); //获取类TestDll的对象
#endif // TESTDLL_H
TestDll.cpp源码
#include <iostream>
#include "TestDll.h"TestDll::TestDll()
{}TestDll::~TestDll()
{}void TestDll::helloWorld()
{std::cout << "hello,world!";
}TestDll* getTestDll()
{return new TestDll();
}
TestMain项目中的main.cpp源码
#include <QtCore/QCoreApplication>
#include <iostream>
#include <QLibrary>
#include "../TestDll/TestDll.h" //头文件还是需要加的,否则无法解析TestDll类
typedef TestDll* (*GetTestDll)();//定义函数指针,获取类TestDLL对象;
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);QLibrary mylib("TestDll.dll"); //声明所用到的dll文件int result;//判断是否正确加载if (mylib.load()) {GetTestDll getTestDll = (GetTestDll)mylib.resolve("getTestDll");if(getTestDll){TestDll *testDll = getTestDll();testDll->helloWorld();delete testDll;}}//加载失败elsestd::cout << "DLL is not loaded!"<<std::endl;return a.exec();
}
这个方法的使用得用户可以很容易地为你的程序制作插件。它的缺点是创建对象的内存必须在dll中分配
②用GetProcAddress直接调用类对象中的成员函数
这个方法,我没测试,对我没对大作用,还得用def导出DLL函数,有兴趣的就参考一下这篇文章。DLL中类的显式链接
③用Qt的QPluginLoader类直接调用生成的DLL插件类对象
这个方法,我单独写一篇总结,请看QPluginLoader的简单小例子VS2008+Qt 使用QPluginLoader访问DLL
3、采用隐式链接方法,通过QLibrary类对DLL中类对象、全局函数的调用
TestDll.h
#ifndef TESTDLL_H
#define TESTDLL_H#include "testdll_global.h"class TESTDLL_EXPORT TestDll
{
public:TestDll();~TestDll(); void helloWorld(); //类成员函数
private:};
extern "C" TESTDLL_EXPORT int add(int a,int b); //自定义的外部函数
#endif // TESTDLL_H
TestDll.cpp源码
#include <iostream>
#include "TestDll.h"TestDll::TestDll()
{}TestDll::~TestDll()
{}void TestDll::helloWorld()
{std::cout << "hello,world!";
}
int add(int a,int b)
{return a + b;
}
TestMain项目中的main.cpp ,需要稍微配置头文件和lib文件
1、在项目中主程序引入TestDll.h头文件,
2、配置项目属性:加入TestDLL.lib的文件目录,在Linker/General/Additional Library Diretories里面选择TestDll.lib的文件目录D:\VSWorkSpace\Test\Debug
3、配置项目属性:加入TestDll.lib文件,在Linker/Input/Additional Dependencies 中加入 TestDll.lib
main.cpp源码
#include <QtCore/QCoreApplication>
#include <iostream>
#include <QLibrary>
#include "../TestDll/TestDll.h"
//引入TestDll.lib文件,和上面的2,3步工作同理
//#pragma comment(lib, "../Debug/TestDll.lib")
int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);int result = add(5,6);std::cout << result;TestDll dll;dll.helloWorld();return a.exec();
}
结果即可编译成功
Qt DLL总结【二】-创建及调用QT的 DLL相关推荐
- Qt DLL总结-创建及调用QT的 DLL
目录 Qt DLL总结[一]-链接库预备知识 Qt DLL总结[二]-创建及调用QT的 DLL Qt DLL总结[三]-VS2008+Qt 使用QPluginLoader访问DLL 开发环境:VS20 ...
- android调用 qt so文件路径,Android Java调用Qt写的so库
有时候,我们反编译apk得到一个so库,如果直接使用这个so库的话,必须使用原来so库同样的package名字,才能用.这样人家反编译你的apk,就知道你侵犯了人家的版权.为了达到混淆的目的,我们可以 ...
- Qt OpenGL(二十八)——Qt OpenGL 核心模式-绘制一个正方体(正六面体)
Qt OpenGL(二十七)--Qt OpenGL 核心模式-绘制一个正方体(正六面体) 截止到上一篇文章,一川想使用Qt封装的类绘制一个旋转的彩色三角形的目标就实现了. 上一篇在介绍了使用变换矩阵的 ...
- dll窗体的创建与调用
建立DLL项目: library ShowDllForm; .... Uses ... Exports //输出引用 ShowDllModalForm, //显示模态窗体 ShowDllForm; / ...
- C++ dll 动态链接库的创建与调用
/********************************************************/ /*DLL中的函数定义*/ /*计算x+y的值*/ int __declspec( ...
- Qt基础之二十六:Qt绘图系统(Paint System)
Qt的绘图系统允许使用相同的API在屏幕和其它打印设备上进行绘制.整个绘图系统基于QPainter,QPainterDevice和QPaintEngine三个类. QPainter用来执行绘制的操作: ...
- Qt DLL总结【三】-VS2008+Qt 使用QPluginLoader访问DLL
目录 Qt DLL总结[一]-链接库预备知识 Qt DLL总结[二]-创建及调用QT的 DLL Qt DLL总结[三]-VS2008+Qt 使用QPluginLoader访问DLL 开发环境:VS20 ...
- Qt入门01 创建第一个Qt程序
一.安装Qt及Qt Creator 1.Qt下载地址 常用的工具也在这些地方可以找到,当然也可以直接官网下载,考入到网速因素,国内的镜像源网站还是要更快一些.Qt 5.15 之后已经不提供离线安装包了 ...
- delphi dll创建及调用
第一章 DLL简单介绍 由于在目前的学习工作中,需要用到DLL文件,就学习了下,在这里作个总结. 首先装简单介绍下DLL: 1,减小可执行文件的大小 DLL技术的产生有很大一部分原因是为了减小可执行文 ...
最新文章
- 【工业串口和网络软件通讯平台(SuperIO)教程】七.二次开发服务驱动
- MATLAB实战系列(十七)-大学生数学建模赛题解析-水塔中水流量估计(附MATLAB源码)
- 凝思系统如何调节分辨率_如何消除步进电机的噪音和振动?
- Windows Internet Explorer 8 简体中文正式版发布!
- STM32 DAP仿真器使用 F103系列
- Android源码设计模式探索与实战【建造者模式】
- 记录: 问题:/usr/bin/ld: main.o: Relocations in generic ELF (EM: 183)
- ORB-SLAM2代码详解09: 闭环线程LoopClosing
- python pandas 实战 百度音乐歌单 数据分析
- 默纳克万能协议服务器图片,默纳克MDKE6万能协议 使用说明...
- OpenCV学习笔记(5)_ ellipse绘制函数浅析
- 组态王软件与200smart无线以太网通信方案详解
- 项目管理工具——SWOT分析法
- 机器人足球仿真第二次作业
- SCI文献阅读报告模板
- 2020华科软件学院 软件体系结构考试回忆
- Unity UI系统--image组件
- java 部署_JAVA项目服务器部署
- 【Qt】 关于垂直同步 以及在Window 下的一个关闭垂直同步动画过快的问题-暂未找到解决方案
- 工作经验背景调查包含的内容和注意事项?
热门文章
- Atcoder Yahoo Programming Contest 2019 简要题解
- 2017-2018-2课表
- Android开发中使用startActivityForResult()方法从Activity A跳转Activity B出现B退出时A也同时退出的解决办法...
- Vivado常见问题集锦
- WPF: 结束程序及关闭所有窗口
- Android_自定义控件样式
- 【python】列表的定义与操作
- 测试负责人和测试工程师在日常工作有什么不同
- JMETER badboy 录制脚本
- android contentresolver 批量,Android之使用ContentResolver对通信录中的数据进行简单操作...