在QT中调用动态链接库DLL的导出函数
在QT中调用DLL的导出函数有4钟方法:
第一种:使用Win32API函数
第二种:使用Qt自带的API函数
第三种:直接调用DLL
第四种:可视化操作(点点鼠标即可)
实验准备:DLL项目文件,本次教程准备了Test项目(_declspec(dllexport)导出)
,里面包含了我们后面需要导出的f()
函数,用的VS2022生成,具体怎么生成可以参考我之前的博客利用VS2022生成动态链接库的两种方法
为了更容易上手,这里就先介绍第三、第四种,最简单也是最容易理解的方式
第四种:可视化操作(点点鼠标即可)
(1)在Qt Creater创建一个项目UseDll2,至于是对话框还是窗口项目都无所谓,我这里现在选择的是基于widget项目,带ui,主要是通过一个按钮来实现动态库函数的调用。项目创建成功后,准备好下面的文件,并在ui放置一个按钮。widget.cpp中记得要包含test.h文件。各个文件里面的内容在图中给出,比较简单就不赘述。
(2)右键点击项目,选择添加库
选择外部库
然后把 库文件 和 库 所在的路径添加上去(就是我们Test项目生成的dll文件路径,按照自己的来就行),此外,具体哪些该勾不该勾的,可以参考下图
点击下一步之后,你的QT项目的.pro文件中就会自动加入以下语句,点击完成就行
接下来直接运行项目,点击按钮,就会调用DLL中的导出函数f()
第三种:直接调用DLL
第三种调用方法和第四种本质上是一样的,只是添加在QT项目的.pro文件中的语句是自己手动填写。具体的格式如下:
LIBS += -L$$PWD/./ -lTest
其中LIBS
指明要加入的是库的路径;-L
表示导入库文件的路径;$PWD
表示当前的路径;-l
后面紧接着就是导入库的名称Test
,不需要带后缀。
按照上面的格式,我们直接在.pro文件中的# Default rules for deployment.
上面一行添加下面这句代码就行了(按照自己对应的路径),其它操作和方法四是一样的,最后也能成功调用。
至此,两种简单快捷的方式就已经介绍完了,下面的两种就是要靠具体的代码实现了,也是有一定的模板格式,主要是依靠句柄来实现的,本文不做过多展开,只给出主要代码,后续有需要再更新吧!
第一种:使用Win32API函数
在UseDll项目中按钮对应的槽函数中写入如下代码,主要就是通过内置的LoadLibrary()
函数读取对应库的路径,然后通过GetProcAddress()
函数来获取导出函数的内存地址,GetLastError()
函数是用来获取错误码用的。
void Widget::on_pushButton_clicked() //Win32API函数调用动态链接库
{
DWORD dw;
HINSTANCE hDLL; // Handle to DLL
FUNC lpfnDllFunc1; // Function pointer
QString str;
hDLL = ::LoadLibrary(L"D:/QtProject/Test/x64/Debug/Test.dll");
if (hDLL)
{
lpfnDllFunc1 = (FUNC)GetProcAddress(hDLL,"f");
if (!lpfnDllFunc1)
{
// handle the error
dw = ::GetLastError();
FreeLibrary(hDLL);
str=QString::asprintf("GetProcAddress failed:%d",dw);
QMessageBox::information(this,"Error code",str);
}
else
{
// call the function
lpfnDllFunc1();
}
}
else
{
dw = ::GetLastError();
str=QString::asprintf("Load dll failed:%d",dw);
QMessageBox::information(this,"Error",str);
}
}
注意:在对应的.cpp文件中,要填上下面这条语句 typedef void ( * FUNC)();
点击对应的按钮,也能调用成功
第二种:使用Qt自带的API函数
同样,在UseDll项目中按钮对应的槽函数中写入如下代码,其中QLibrary()
函数是Qt本身就有相应的类,通过它可以加载动态链接库
void Widget::on_pushButton_3_clicked()//Qt自带的API函数调用动态链接库
{
FUNC myfunc;
QLibrary lib("D:/QtProject/Test/x64/Debug/Test.dll");
if(lib.load())
{
myfunc = (FUNC)lib.resolve("f");
if (!myfunc)
{
QMessageBox::information(this,"Error","resolve failed"); // 处理错误情况
}
else
{
myfunc(); //调用导出函数
}
}
else QMessageBox::information(this,"Error","load failed");
}
同样,在对应的.cpp文件中,要填上下面这条语句 typedef void ( * FUNC)();
最后运行项目,发现调用成功