`
qimo601
  • 浏览: 3449432 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

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;
				}
			else
				std::cout << "Link to add Function failed!!"<<std::endl;

			
	}
	//加载失败
	else
		std::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;
			}
	}
	//加载失败
	else
		std::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();
}

 结果即可编译成功

8
0
分享到:
评论
4 楼 857554769 2014-01-16  
Thanks
3 楼 qimo601 2012-11-02  
wolfguolei 写道
你好哥们,
    我看了你写的关于Qt中DLL的使用,非常适用。只是现在有个问题,你在这些内容里没写,我遇到了也不知道什么原因。弄了好几天也没弄出来,特来向你请教。我封装了一个DLL库,按照你所提倡的方法,但是接口函数返回了一个指针是我自定义类的类型。现在我在工程中调用这个DLL库,并且包含了头文件。但是编译的时候总是不通过,QT显示返回值类型未定义(虽然我已经按照你的做法包含了头文件)。但是,当我将制作DLL所用到的CPP文件加入工程中(加进PRO文件中),一切就OK了。望哥们百忙之中能帮我分析分析。我的QQ:214792543,欢迎做个朋友。


请将.dll放在exe所在目录下就可以了
2 楼 qimo601 2012-11-02  
wolfguolei 写道
你好哥们,
    我看了你写的关于Qt中DLL的使用,非常适用。只是现在有个问题,你在这些内容里没写,我遇到了也不知道什么原因。弄了好几天也没弄出来,特来向你请教。我封装了一个DLL库,按照你所提倡的方法,但是接口函数返回了一个指针是我自定义类的类型。现在我在工程中调用这个DLL库,并且包含了头文件。但是编译的时候总是不通过,QT显示返回值类型未定义(虽然我已经按照你的做法包含了头文件)。但是,当我将制作DLL所用到的CPP文件加入工程中(加进PRO文件中),一切就OK了。望哥们百忙之中能帮我分析分析。我的QQ:214792543,欢迎做个朋友。


根据你叙说的,我猜测,你是用隐式链接调用DLL文件。你包含了头文件,配置好了lib文件,编译不通过,但假如源文件就可以编译通过。所以我猜测你没有将DLL文件放在你的项目Debug程序下。请将.dll放在exe所在目录下就可以了。 


==========================DLL常识=============================
为隐式链接到 DLL,可执行文件必须从 DLL 的提供程序获取下列各项:

包含导出函数和/或 C++ 类的声明的头文件(.H 文件)
要链接的导入库(.LIB files)。(生成 DLL 时链接器创建导入库。)
实际的 DLL(.DLL 文件)

隐 式链接需要一个由动态连接库产生的.LIB文件(导入库),并把它链接到应用程序的工程中.该导入库仅包含加载DLL的代码和实现DLL函数调用的代码。 在导入库中找到外部函数后,会通知链接器此函数的代码在DLL中。要解析对DLL的外部引用,链接器只需向可执行文件中添加信息,通知系统在进程启动时应 在何处查找 DLL 代码。

系统启动包含动态链接引用的程序时,它使用程序的可执行文件中的信息定位所需的DLL。如果系统无法定位 DLL,它将终止进程并显示一个对话框来报告错误。如果找到了DLL,系统将DLL模块映射到进程的地址空间中。与程序代码的其余部分一样,DLL代码在 进程启动时映射到进程的地址空间中,且仅当需要时才加载到内存中。

Windows将遵循下面的搜索顺序来定位DLL

包含EXE文件的目录
进程的当前工作目录
Windows系统目录(system/system32)。GetSystemDirectory 函数检索此目录的路径。
Windows目录.GetWindowsDirectory 函数检索此目录的路径。
列在Path环境变量中的一系列目录
1 楼 wolfguolei 2012-10-30  
你好哥们,
    我看了你写的关于Qt中DLL的使用,非常适用。只是现在有个问题,你在这些内容里没写,我遇到了也不知道什么原因。弄了好几天也没弄出来,特来向你请教。我封装了一个DLL库,按照你所提倡的方法,但是接口函数返回了一个指针是我自定义类的类型。现在我在工程中调用这个DLL库,并且包含了头文件。但是编译的时候总是不通过,QT显示返回值类型未定义(虽然我已经按照你的做法包含了头文件)。但是,当我将制作DLL所用到的CPP文件加入工程中(加进PRO文件中),一切就OK了。望哥们百忙之中能帮我分析分析。我的QQ:214792543,欢迎做个朋友。

相关推荐

    QT调用dll和MFC调用QT的dll

    - MFC调用:在MFC项目中,同样使用`LoadLibrary`和`GetProcAddress`加载并调用QT DLL中的函数。 5. 注意事项: - 动态链接库的版本匹配:确保QT和MFC使用的库版本一致,避免兼容性问题。 - 环境设置:确保所有的...

    QT调用mfc dll和qt dll

    - MFC项目通过`LoadLibrary`和`GetProcAddress`调用QT DLL。 5. QT调用QT DLL: - QT支持更方便的插件系统(QPluginLoader),允许在运行时加载和使用QT DLL。 - 在DLL中定义一个类继承自`QObject`,并使用`Q_...

    Java调用Qt DLL

    Java调用Qt DLL是一个跨平台的技术实践,涉及到Java与C++之间的互操作性,其中Qt是一个流行的C++库,主要用于图形用户界面开发。这个主题主要包含以下几个知识点: 1. **JNI(Java Native Interface)**:JNI是Java...

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

    本篇文章将深入探讨如何在QT中创建和调用Dll中的方法,特别是类成员方法,我们将按照以下步骤进行详细讲解。 首先,了解DLL的基本概念。DLL(Dynamic Link Library)是Windows操作系统中的一种共享库,它可以被多个...

    将QT界面做成dll在qt其他程序中调用

    这个过程涉及到QT的库使用、DLL的创建以及如何在不同的QT应用程序中调用DLL中的功能。下面我们将详细探讨这些知识点。 1. **QT库的管理**: - QT库分为静态库和动态库两种形式。静态库将所有依赖项打包到可执行...

    QT-DLL库调用.zip

    总结起来,QT-DLL库调用涉及到的关键知识点包括C++动态链接库的创建、Qt项目配置、QLibrary的使用、动态加载和卸载DLL以及错误处理。掌握这些技能,将使你在开发复杂跨平台应用程序时更具灵活性和效率。

    QT编写DLL调用示例 方法 参数 返回值 事件回调

    qtdll dll&quot; ] public static extern int add int i ; 第三步:调用函数执行; Console WriteLine add 10 ToString ; 2:QT 第一步:引入头文件; #include &lt;QLibrary&gt; 第二步:定义函数指针 以备调用; ...

    C#调用QT的dll方法

    C#调用QT的dll方法 在这篇文章中,我们将讨论如何在C#中调用QT的dll方法。首先,我们需要在QT平台上建立一个dll工程,设置头文件和源文件,然后生成dll文件。最后,我们可以在C#中使用DllImport特性来调用dll方法。...

    c#调用qt dll

    总结来说,C#调用Qt DLL涉及的关键点有: - 使用P/Invoke特性进行跨语言互操作。 - 正确地定义C#接口以匹配DLL函数的签名,包括参数类型和调用约定。 - 对于回调函数,使用委托在C#中封装方法,并传递给DLL。 - 注意...

    Qt创建带界面的DLL给C#调用案例-20221226.zip

    C# 与 Qt 混合编程,开发软件。 Qt编写功能模块给C#调用。...这个例子是一个完整的播放器例子,也就是Qt+mpv开发视频播放器给C#调用,主要是介绍Qt编译成DLL,导出接口给C#调用整体流流程,以及接口使用。

    MFC程序调用Qt(DLL)界面显示

    综上所述,通过在MFC程序中调用Qt DLL,我们可以充分利用Qt的UI设计优势,同时保持MFC项目的结构和兼容性。这个过程涉及Qt和MFC项目的创建、接口设计、库的引用以及线程管理等多个方面,需要仔细处理每一个细节。...

    Qt直接调用动态库dll

    1. **创建或获取DLL**:你需要有一个编译好的DLL文件,其中包含你想要在Qt应用中使用的函数或类。这通常通过C++代码编写,并使用Visual Studio或其他编译器生成。 2. **定义接口**:DLL中的函数或类需要有明确的...

    QT5中调用DLL

    打开并运行此项目,可以直观地了解DLL调用的过程。 5. **注意事项**: - 确保DLL和应用程序使用相同的编译器和运行时库(如MSVC或MinGW),否则可能会遇到运行时错误。 - 为了在不同平台上运行,需要为每个目标...

    qt dll调用实例

    总结,"qt dll调用实例"主要涉及Qt环境下如何创建和使用DLL,包括配置项目、加载和调用DLL函数,以及可能的错误处理和调试技巧。同时,结合`adb`,可能还涵盖了Qt与Android设备通信的实践。理解这些知识点对于在...

    c#调用QTdll的框架(包含案例)

    c#调用QTdll的框架(包含案例),可以成功运行,自己创建一个C#窗口程序就可以调用, 调用的时候别忘了将dll所依赖的dll放在同一目录下,否则会报试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)。

    QT生成带界面的dll给c#调用

    build-qtdll-Desktop_Qt_5_12_2_MSVC2015_64bit-Release文件夹是qt编译生成的文件夹;QtReleaseDll文件夹里面是最重要的qtdialog.dll以及他所依赖的所有的库;CsharpUseQtDll文件夹里面是c#工程。 具体使用细节参见...

    Qt.VC调用delphi编写的dll lib,详细方法

    Delphi以其强大的面向对象特性及易用性,在创建高效、快速的Windows应用程序时受到青睐,而它的DLL库能为其他语言提供接口。本教程将详细介绍如何在Qt或VC项目中调用由Delphi编写的DLL库,并生成相应的lib文件,以...

    Qt 创建dll实例

    ### Qt 创建 DLL 实例详解 #### 一、创建 DLL 工程 在开始之前,我们需要了解如何使用 Qt 创建 DLL(动态链接库)。本教程将详细地介绍整个过程,包括创建项目、配置设置、编写代码以及如何与其他应用程序进行交互...

    QT动态链接库(DLL)的创建和调用

    QT动态链接库(DLL)是软件开发中常用的一种技术,它允许将代码和资源打包成独立的可加载模块,可以在运行时被多个程序共享,从而节省内存并提高系统效率。在Windows平台上,DLL文件是执行文件的一种特殊形式,可以...

    qt 调用库函数(DLL、LIB)

    总结来说,Qt调用库函数涉及到库的编译、链接、库路径设置、头文件导入以及函数调用等多个环节。正确理解和操作这些步骤,可以有效地整合Qt与第三方库,构建功能强大的应用程序。在实际项目中,务必注意库的版本兼容...

Global site tag (gtag.js) - Google Analytics