先讲一下对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 文件源代码一直不变

  1. #ifndef TESTDLL_GLOBAL_H
  2. #define TESTDLL_GLOBAL_H
  3. #include <QtCore/qglobal.h>
  4. #ifdef TESTDLL_LIB
  5. # define TESTDLL_EXPORT Q_DECL_EXPORT
  6. #else
  7. # define TESTDLL_EXPORT Q_DECL_IMPORT
  8. #endif
  9. #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源码

  1. #ifndef TESTDLL_H
  2. #define TESTDLL_H
  3. #include "testdll_global.h"
  4. class TESTDLL_EXPORT TestDll
  5. {
  6. public:
  7. TestDll();
  8. ~TestDll();
  9. private:
  10. };
  11. extern "C" TESTDLL_EXPORT void helloWorld();
  12. extern "C" TESTDLL_EXPORT int add(int a,int b);
  13. #endif // TESTDLL_H

TestDll.dll项目中的TestDLL.cpp源码

  1. #include <iostream>
  2. #include "TestDll.h"
  3. TestDll::TestDll()
  4. {
  5. }
  6. TestDll::~TestDll()
  7. {
  8. }
  9. void helloWorld()
  10. {
  11. std::cout << "hello,world!";
  12. }
  13. int add(int a,int b)
  14. {
  15. return a + b;
  16. }

注: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

  1. #include <QtCore/QCoreApplication>
  2. #include <iostream>
  3. #include <QLibrary>
  4. typedef int (*Fun)(int,int); //定义函数指针,int add(int a,int b);
  5. int main(int argc, char *argv[])
  6. {
  7. QCoreApplication a(argc, argv);
  8. QLibrary mylib("TestDll.dll");   //声明所用到的dll文件
  9. int result;
  10. //判断是否正确加载
  11. if (mylib.load())
  12. {
  13. std::cout << "DLL load is OK!"<<std::endl;
  14. //调用外部函数 add()
  15. Fun add = (Fun)mylib.resolve("add");
  16. //是否成功连接上 add() 函数
  17. if (add)
  18. {
  19. std::cout << "Link to add Function is OK!"<<std::endl;
  20. //这里函数指针调用dll中的 add() 函数
  21. result = add(5,6);
  22. std::cout << result;
  23. }
  24. else
  25. std::cout << "Link to add Function failed!!"<<std::endl;
  26. }
  27. //加载失败
  28. else
  29. std::cout << "DLL is not loaded!"<<std::endl;
  30. return a.exec();
  31. }

2、采用显示链接,调用C++类中的类对象、成员函数 

如果你想导出并显式链接一组C++类中的成员函数又该怎么办呢?这里有两个问题。第一是C++成员函数名是经过修饰的(即使指定extern "C"标记也是这样);第二是C++不允许将指向成员函数的指针转换成其它类型。这两个问题限制了C++类的显式链接。下面介绍两种方法来解决这个问题:

①用虚函数表的方法,这也是COM使用的方法,利用Qt的QLibrary技术调用;

②用GetProcAddress直接调用。

用Qt的QPluginLoader类直接调用生成的DLL插件类对象

①虚函数表的方法,QLibrary 技术调用

TestDll.h代码

  1. #ifndef TESTDLL_H
  2. #define TESTDLL_H
  3. #include "testdll_global.h"
  4. class TESTDLL_EXPORT TestDll
  5. {
  6. public:
  7. TestDll();
  8. virtual~TestDll();
  9. virtual void helloWorld(); //类成员函数
  10. private:
  11. };
  12. extern "C" TESTDLL_EXPORT TestDll* getTestDll(); //获取类TestDll的对象
  13. #endif // TESTDLL_H

TestDll.cpp源码

  1. #include <iostream>
  2. #include "TestDll.h"
  3. TestDll::TestDll()
  4. {
  5. }
  6. TestDll::~TestDll()
  7. {
  8. }
  9. void TestDll::helloWorld()
  10. {
  11. std::cout << "hello,world!";
  12. }
  13. TestDll* getTestDll()
  14. {
  15. return new TestDll();
  16. }

TestMain项目中的main.cpp源码

  1. #include <QtCore/QCoreApplication>
  2. #include <iostream>
  3. #include <QLibrary>
  4. #include "../TestDll/TestDll.h"  //头文件还是需要加的,否则无法解析TestDll类
  5. typedef TestDll* (*GetTestDll)();//定义函数指针,获取类TestDLL对象;
  6. int main(int argc, char *argv[])
  7. {
  8. QCoreApplication a(argc, argv);
  9. QLibrary mylib("TestDll.dll");   //声明所用到的dll文件
  10. int result;
  11. //判断是否正确加载
  12. if (mylib.load())
  13. {
  14. GetTestDll getTestDll = (GetTestDll)mylib.resolve("getTestDll");
  15. if(getTestDll)
  16. {
  17. TestDll *testDll = getTestDll();
  18. testDll->helloWorld();
  19. delete testDll;
  20. }
  21. }
  22. //加载失败
  23. else
  24. std::cout << "DLL is not loaded!"<<std::endl;
  25. return a.exec();
  26. }

这个方法的使用得用户可以很容易地为你的程序制作插件。它的缺点是创建对象的内存必须在dll中分配

②用GetProcAddress直接调用类对象中的成员函数

这个方法,我没测试,对我没对大作用,还得用def导出DLL函数,有兴趣的就参考一下这篇文章。DLL中类的显式链接

用Qt的QPluginLoader类直接调用生成的DLL插件类对象

这个方法,我单独写一篇总结,请看QPluginLoader的简单小例子VS2008+Qt 使用QPluginLoader访问DLL

3、采用隐式链接方法,通过QLibrary类对DLL中类对象、全局函数的调用

TestDll.h

  1. #ifndef TESTDLL_H
  2. #define TESTDLL_H
  3. #include "testdll_global.h"
  4. class TESTDLL_EXPORT TestDll
  5. {
  6. public:
  7. TestDll();
  8. ~TestDll();
  9. void helloWorld(); //类成员函数
  10. private:
  11. };
  12. extern "C" TESTDLL_EXPORT int add(int a,int b);  //自定义的外部函数
  13. #endif // TESTDLL_H

TestDll.cpp源码

  1. #include <iostream>
  2. #include "TestDll.h"
  3. TestDll::TestDll()
  4. {
  5. }
  6. TestDll::~TestDll()
  7. {
  8. }
  9. void TestDll::helloWorld()
  10. {
  11. std::cout << "hello,world!";
  12. }
  13. int add(int a,int b)
  14. {
  15. return a + b;
  16. }

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源码

  1. #include <QtCore/QCoreApplication>
  2. #include <iostream>
  3. #include <QLibrary>
  4. #include "../TestDll/TestDll.h"
  5. //引入TestDll.lib文件,和上面的2,3步工作同理
  6. //#pragma comment(lib, "../Debug/TestDll.lib")
  7. int main(int argc, char *argv[])
  8. {
  9. QCoreApplication a(argc, argv);
  10. int result = add(5,6);
  11. std::cout << result;
  12. TestDll dll;
  13. dll.helloWorld();
  14. return a.exec();
  15. }

结果即可编译成功

qt 创建及调用QT的 DLL的更多相关文章

  1. Qt DLL总结【二】-创建及调用QT的 DLL(三篇)good

    目录 Qt DLL总结[一]-链接库预备知识 Qt DLL总结[二]-创建及调用QT的 DLL Qt DLL总结[三]-VS2008+Qt 使用QPluginLoader访问DLL 开发环境:VS20 ...

  2. Qt DLL总结【二】-创建及调用QT的 DLL

    开发环境:VS2008+Qt4.7.4 最近看了不少Qt的DLL例子,总结一下如何创建和调用QT 动态链接库. 先讲一下对QT动态链接库的调用方法,主要包括: 1.显式链接DLL,调用DLL的全局函数 ...

  3. QT创建与调用Dll方法(包括类成员)--显式调用

    看网上的好多关于QT调用Dll的方法,大部分都是调用函数的,并没有调用C++类成员的情况,即使是有,比如说: 使用Qt编写模块化插件式应用程序 Qt 一步一步实现dll调用(附源码)---(这一篇里没 ...

  4. Qt生成和调用动态库dll,和静态库.a(windows和linux通用)

    系统1:ThinkPad T570.Windows10.QT5.12.2(Qt Creater 4.8.2)一.动态库.dll的创建和调用1.在qtcreater中按如下步骤创建动态库,动态库名为my ...

  5. QT共享库的创建与调用(初级)(附:UI界面不能被改变的其中一个原因)

    背景: 最近在做的一个项目其中一部分既是实现PC与下位机的USB通信.windows平台下已经完成,现需移植到linux平台下. 在linux系统中,通过一段时间的工作,设备已被配置成hid类(后续再 ...

  6. Qt Dll总结(二)——创建及使用Qt的Dll(转载)

    先讲一下对QT动态链接库的调用方法,主要包括: 1.显式链接DLL,调用DLL的全局函数,采用Qt的QLibrary方法 2.显示链接DLL,调用DLL中类对象.成员函数.(通过对象即可实现类成员函数 ...

  7. QT源码解析(七)Qt创建窗体的过程,作者“ tingsking18 ”(真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法)

    前言:分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法, ...

  8. QT中QProcess调用命令行的痛苦经历(调用Winrar,设置工作目录,获得输出,注意引号与括号,等等)

    QT中QProcess调用命令行的痛苦经历   阅读目录 创建压缩包的方法 在QT中调用命令行 在QT中调用C++创建的dll 在QT程序中需要将某些目录和文件压缩为一个rar的压缩包,于是想到了在Q ...

  9. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...

随机推荐

  1. elment 中tree组件展开所有和收缩所有

    upAll () { // 全部展开 遍历变成true let self = this; // 将没有转换成树的原数据 let treeList = this.sourceData; for (let ...

  2. MVC模板页使用

    这里我们要做一个公共的模板,样式如下: 内容 ·asp.net mvc如何创建模板??1.在/Views/Shared/中右键-添加-视图 2.重命名为”HeadLayout”,勾选”创建为分部视图” ...

  3. perl语言的线程使用

    参考的教程链接是 https://www.cnblogs.com/migrantworkers/p/6973459.html 1.Perl 多线程的使用,join 和 detach 的区别 ,join ...

  4. 数据库之sqlite

    数据创建数据 CREATE TABLE IF NOT EXISTS ArpAudit (ID INTEGER PRIMARY KEY autoincrement NOT NULL, UserName ...

  5. ASE —— 第二次结对作业

    目录 重现基线模型 基线模型原理 模型的优缺点 模型重现结果 提出改进 改进动机 新模型框架 评价合作伙伴 重现基线模型 基线模型原理 我们选用的的模型为DeepCS,接下来我将解释一下它的原理. 我 ...

  6. Python——DataFrame转list(包含两种)

    import pandas as pd df = pd.DataFrame({'a':[1,3,5,7,4,5,6,4,7,8,9], 'b':[3,5,6,2,4,6,7,8,7,8,9]}) df ...

  7. Java基础 @org.junit.Test-单元测试方法 + 操纵Collection和Map的工具类 : Collections 的sort/binarySearch/max/min等静态方法

      单元测试代码:  ( 在IDEA中先输入'@Test '然后根据提示进行自动修订即可!!运行时直接运行即可! 若有多个单元测试块的时候,直接把鼠标放在哪里就自动在哪里运行那个单元块) import ...

  8. 201871010111-刘佳华《面向对象程序设计(java)》第十七周学习总结

    201871010111-刘佳华<面向对象程序设计(java)>第十七周学习总结 实验十七  线程同步控制 实验时间 2019-12-20 第一部分:理论知识总结 16.Java 的线程调 ...

  9. PWA

    附一个示例e6书写 todolist的示例,切换list的状态: //todolist示例 const toggleTodo = (id)=>{ setTodos(todos => tod ...

  10. EL表达式,JSP内置对象

    基本语法格式 EL都是以 ${ 为起始.以} 为结尾的 ${ EL Expression} 示例: ${ “Helloworld” }  //输出字符串常量 ${ str }  //输出字符串变量st ...