QT调VC的DLL实验总结
来源:互联网 发布:arch linux 安装教程 编辑:程序博客网 时间:2024/05/16 12:05
本文主要介绍”如何在Qt程序中调用VC的DLL库“,包括:隐式加载和显式加载、编译选项、导出函数、调用约定和错误分析。
一、开发环境
1,Qt5.4.1 + MinGW Compiler,生成Caller程序。
2,VS2015,生成win32 DLL库。
二、隐式加载
1,新建VC的DLL
使用VS2015新建win32 DLL项目 —— TestDll。添加如下代码:
// TestDll.cpp : 定义 DLL 应用程序的导出函数。//#include "stdafx.h"extern "C" int __declspec(dllexport) __stdcall Foo(int a, int b){ return a + b;}
1)它使用C方式导出函数。
2)它使用__stdcall调用约定,VS默认为__cdecl,故此处要显示注明。
2,新建Qt的Caller.exe
使用QCreator新建Qt控制台应用程序。并进行如下修改:
1)在.pro文件添加导出库的.lib文件所在位置和名字。如下:
LIBS += -L $$_PRO_FILE_PWD_/Lib -l TestDll它实际上就是添加了一条编译命令 —— LIBS,其中附带选项”-L“(大写),其值为.lib文件所在目录。我在此使用的是”$$_PRO_FILE_PWD“宏,其中前两个符号是路径抽取符,后面的宏是指.pro所在路径,同时,我需要在该路径下新建一个文件夹”Lib“,并把”TestDll.lib“文件放在里面。此外,需要注意的是,Qt中的路径字符串遵循Linux标准,使用的是斜杠(slash),Windows实际使用反斜杠(backslash)。
该编译命令的第二个选项是”-l"(小写),它指定.lib文件名,不带后缀,这样可以兼容Windows下的.dll和Linux下的.so文件。
2)在“main.cpp”中声明被调函数。
extern "C" int __stdcall Add(int, int);在实际项目中,可以直接包含导出库的.h文件。但是,需要指定.h文件的路径,它需要在.pro中添加“INCLUDEPATH”编译命令。
3)调用测试
在main函数中直接调用
int result = Add(2, 3)
5)将TestDll.dll文件拷贝到运行目录下,即和Caller.exe在同一个目录下。
如此,程序即可正常编译和运行,并可debug查看正确调用后的结果 —— “result 的值为5”。
3,错误分析
1)如果没有将.lib文件放到指定位置,编译时将报链接错误,找不到指定的lib文件。
2)如果函数导出方式(extern ”C“)不一致,或者调用约定不一致(__stdcall或__cdecl),编译时将报链接错误,找不到指定的导出函数。
3)如果.dll文件没有放到”可执行文件目录“,不会报编译错误,在运行时将弹错误框“执行失败”,并显示“During startup programexited with code 0xc0000135”。
综上,隐式加载方式在编译阶段会去解析.lib文件,并将导出函数符号链接到程序中。而真正的库函数,是在程序启动阶段进行加载。
三、显式加载
Qt显式加载主要是利用QLibrary类。
QLibrary lib("TestDll");lib.load();int result = 0;if (lib.isLoaded()){ typydef int(*FuncPtr)(int, int); FuncPtr pFunc = (FuncPtr)lib.resolve("Add"); if (pFunc) result = pFunc(2, 3);}
1)它实际上是在运行时通过resolve函数去.dll文件中找导出函数符“Add",找到后返回该函数的地址,实际上是一个偏移量。
2)可以用void*去接收resolve的返回值,后面调用的时候再转换为对应的函数指针。
3)该方法在我的实验来看,只适合”__cdecl“调用约定导出的函数,如果DLL中的函数使用”__stdcall“方式导出,resolve函数的返回值为”0"。即使将函数指针声明为如下形式:
typydef int(__stdcall*FuncPtr)(int, int);因为,实际上是resolve函数没有解析出相关的导出函数。
相关参考:
Qt5中动态链接库的创建和使用
Qt调用VC的DLL
上文提到的“隐式调用"的方法:
LIBS += -L *** -I ***
该方法只适合MinGw编译器,VC编译器直接用”#pragma comment(lib, "***")",否则报错:
LNK1146:没有选项“:LIBSPATH"指定的参数
命令行编译参考:GccHowTo 和 从C++到Qt
- QT调VC的DLL实验总结
- Qt 调用 VC(CUDA)制作的dll
- VC调用QT的dll 问题解决
- Qt调用vc dll
- QT 调用 vc DLL
- Qt DLL总结【二】-创建及调用QT的 DLL
- Qt DLL总结-创建及调用QT的 DLL
- Qt DLL总结【二】-创建及调用QT的 DLL
- Qt DLL总结-创建及调用QT的 DLL
- QT调用VC dll方法
- VC 2015 x86的DLL绿色包(QT 5.6)
- QT隐式调用VC开发的DLL
- QT显式调用VC开发的DLL
- QT调用vc dll中文乱码的问题
- VC++生成DLL,Qt中使用DLL
- VC++生成DLL,Qt中使用DLL
- VC中dll的生成及使用(本来这几天在QT中用DLL)
- dll的实验备忘
- UML序列图总结--Trufun UML2建模工具
- xcode 7 为创建的项目添加框架
- windows 系统添加到开机启动项
- Codeforces Round #354 (Div. 2) D. Theseus and labyrinth
- poj 3013(最短路变形)
- QT调VC的DLL实验总结
- tableview线条距屏幕的距离
- iOS开发:关于layout的一些方法
- 解决Exception: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z 等一系列问题
- 博弈整理(取物)
- 圈里圈外 | 考什么英语四六级,明明情商二级还没过……
- Leetcode-13. Roman to Integer
- 第四届蓝桥杯决赛 A组 供水设施 dp+拓扑+枚举
- redis Uncaught exception RedisException: Redis server went away