营销型网站建设推广,深圳龙岗是穷人区吗,个人网站取域名,网站建设制作pdf目录 Qt DLL总结【一】-链接库预备知识 Qt DLL总结【二】-创建及调用QT的 DLL Qt DLL总结【三】-VS2008Qt 使用QPluginLoader访问DLL 开发环境#xff1a;VS2008Qt4.7.4 最近看了不少Qt的DLL例子#xff0c;总结一下如何创建和调用QT 动态链接库。 先讲一下对QT动态链接库的… 目录 Qt DLL总结【一】-链接库预备知识 Qt DLL总结【二】-创建及调用QT的 DLL Qt DLL总结【三】-VS2008Qt 使用QPluginLoader访问DLL 开发环境VS2008Qt4.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 文件源代码一直不变 Cpp代码 #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源码 Cpp代码 #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源码 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而是一个形如 ?helloWorldTestDllUAEXXZ”的名字。 为什么名字不是helloworld呢这是因为C为了支持函数的重载会在编译时将函数的参数类型信息以及返回值类型信息加入到函数名中这样代码中名字一样的重载函数在经过编译后就互相区分开了调用时函数名也经过同样的处理就能找到对应的函数了。详细可以看这篇文章动态链接库(Dynamic Link Library)学习笔记 TestMain项目 main.cpp 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类中的类对象、成员函数 【需要TestDLL.dll、TestDll.h】 如果你想导出并显式链接一组C类中的成员函数又该怎么办呢 这里有两个问题。 第一是C成员函数名是经过修饰的即使指定extern C标记也是这样 第二是C不允许将指向成员函数的指针转换成其它类型。这两个问题限制了C类的显式链接。 下面介绍两种方法来解决这个问题 ①用虚函数表的方法这也是COM使用的方法利用Qt的QLibrary技术调用 ②用GetProcAddress直接调用。 ③用Qt的QPluginLoader类直接调用生成的DLL插件类对象 ①虚函数表的方法QLibrary 技术调用 TestDll.h代码 Cpp代码 #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源码 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源码 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的简单小例子VS2008Qt 使用QPluginLoader访问DLL 3、采用隐式链接方法通过QLibrary类对DLL中类对象、全局函数的调用 【需要TestDll.h、TestDll.cpp、TestDll.dll】 TestDll.h Cpp代码 #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源码 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源码 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(); } 结果即可编译成功