C++调用DLL学习笔记——动态调用

C++调用DLL

编译DLL时会生成两个文件,一个是lib, 一个是dll. 注意,此处生成的lib文件和静态库的lib文件不是一个东西。

调用DLL有两种方式:隐式加载、显式加载。

一、隐式加载方式
隐式加载方式下,需要3个文件,分别是dll文件、lib文件以及对应的头文件。例paneldata.dll、paneldata.lib、paneldata.h,将上述文件放入调用程序代码所在目录。

调用代码非常简单,程序中只需要增加两行代码,以下举例说明:

#include<iostream>
#include "paneldata.h" //引入头文件

#pragma comment(lib,"paneldata.lib")  //把lib文件包括进来

int main(){
	int result = paneldata_func1(3.14); //像调用本地函数一样调用外部函数
	cout<< result <<endl;
	return 0;
}

二、显式加载方式
显式加载方式下,调用dll文件只需要为调用者提供一个.dll文件,以及要调用的函数(或类)的名称和参数,将dll文件放入调用程序代码所在目录。

调用有以下步骤:
1、typedef一个与被调用函数类型一致的函数指针。

typedef int (*Dllfunc)(double)
//假设被调用函数返回值为int, 参数类型为double

在这段代码中,Dllfunc的类型被定义为:

“一个指向返回值为int 且 参数类型为double的函数的指针”。

划重点:

typedef 绝不是像 typedef int integer 这么简单——把类型名换个别名。为了深入理解以上代码,建议对此知识点另外深入学习。

2、获得dll文件的句柄。因为是动态调用,dll和可执行文件一起发布,要调用dll,必须先获得它的句柄,要用到一个函数:

HMODULE hDLL = LoadLibrary(dllname); 
//HMODULE 是windows句柄类型,为了使用它,头文件中需包括windows.h

3、定义一个函数指针,用于指向dll中被调用的函数地址,以实现函数功能。

DLLFunc dllfunc;
dllfunc = (DLLFunc)GetProcAddress(hDLL, "paneldata_func1");

现在就可以像使用paneldata_func1()一样来使用dllfunc()了。

最后,别忘了释放dll句柄:

FreeLibrary(hDLL);

完整代码如下:

#include "windows.h"

typedef int (*Dllfunc)(double);

int main(){
	const wchar_t* dllname = L"dll1.dll";
    HMODULE hDLL = LoadLibrary(dllname); 
    //LoadLibrary的参数类型为LPCWSTR(即wchar_t *)
    DLLFunc dllfunc;
    dllfunc = (DLLFunc)GetProcAddress(hDLL, "paneldata_func1");
    //从hDLL文件空间中获得paneldata_func1函数的地址,然后将其强制转换为DLLFunc类型,作为一个函数体传递给dllfunc指针。
    dllfunc(3.1415); //调用了paneldata_func1()
	FreeLibrary(hDLL);
	return 0;
}

关于显式加载的通俗理解

举一个简单的例子,病人到医院看病,首先要挂号,拿着挂号单走进医院,找到对应科室,向医生提供各种检查结果,医生开药。

由于机器人技术的发展,病人现在不用大老远跑到医院了。只需要网上挂了号,通过机器人把检查结果发给医生,医生就能反馈开药结果。

在这个过程中,病人不再需要直接和医院、医生打交道。但为了通过机器人与医院取得联系,病人首先需要一张合法的挂号单,通过挂号单和医院建立联系,医院就相当于dll文件,这个挂号单相当于dll文件的句柄。和医院取得联系后,还要知道科室的位置,需要把科室名称通过机器人告诉医院,由医院返回科室地址。科室名称就相当于我们要调用的函数的名称,而科室地址就是函数在dll文件中的位置。与科室取得联系后,机器人还不能与科室对话,因为不同科室需要的检查结果类型不同,有要CT片子的,有要验血结果的,有要血压血糖的,机器人不知道它应该向病人要什么,所以机器人首先要知道科室需要什么类型的检查结果以及科室开的药物类型,然后自己实现一个和科室完全一样的接口,明确需要的检查结果及类型,并把这个接口展示给病人。这个人机接口就是我们定义的函数指针。通过这个指针,可以把病人的检验结果传递给科室医生,同时能正确接收科室医生开出的药物类型,也就是函数的返回类型。看病完毕后,病人要告诉机器人释放与医院的连接。

完整梳理概念如下:
医院——dll文件
挂号单——dll文件句柄
科室——函数
人机接口——函数指针
检查结果类型——函数参数类型
开药类型——函数返回值类型
获得科室位置——获得函数地址
释放与医院连接——释放dll句柄

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 动态链接库(Dynamic Link Library,简称“DLL”)是一种Windows操作系统下的共享库文件,它可以被多个应用程序共享调用,能够方便多个程序之间共享代码和数据。而动态调用DLL就是在程序运行时,动态地加载DLL文件并执行其的函数,它不需要把DLL文件的函数载入内存,减少了程序的占用空间。 动态调用DLL的过程一般包括以下几步: 1. 加载DLL:程序会使用LoadLibrary函数来加载指定的DLL文件,它返回一个可用于调用DLL函数的句柄。 2. 导入DLL函数:使用GetProcAddress函数,根据DLL函数名称获得函数地址,使其可被调用。 3. 调用DLL函数:将DLL函数地址转换为正确的函数类型,传入参数并调用DLL函数。 4. 卸载DLL:使用FreeLibrary函数卸载已加载的DLL文件,释放内存空间。 动态调用DLL可以使代码更具灵活性和可维护性,适用于需要动态扩展或修改功能的程序。同时,它也提高了程序的效率和整体性能,减少了对系统资源的占用。不过,动态调用DLL需要谨慎使用,因为错误的调用会导致程序崩溃或出现安全漏洞。要注意正确传递函数参数和释放内存空间,避免内存泄漏问题。 ### 回答2: 动态链接库(Dynamic Link Library,DLL)是在Windows系统常用的一种辅助程序。动态调用DLL意味着在运行时加载DLL,并使用其的函数。相比于静态调用(在编译时将DLL函数链接到代码),动态调用具有更大的灵活性和可重用性。 动态链接库通常包括一组函数,这些函数可以通过导出表(Export Table)进行访问。为了使用DLL的函数,首先需要使用LoadLibrary函数将DLL加载到进程的地址空间。加载完成后,还需要使用GetProcAddress函数获取DLL特定函数的地址。 一旦获得了DLL函数的地址,就可以使用类似于函数指针的方式调用它们。通过使用GetProcAddress函数返回的地址指针,将函数的参数传递到DLL函数进行处理。当调用完成后,使用FreeLibrary函数将DLL从进程的地址空间卸载。 总的来说,使用动态调用DLL可以实现在程序运行时动态加载和链接DLL的函数,从而提供更大的灵活性和可重用性。 ### 回答3: 动态调用DLL,是指在程序运行期间,通过代码调用动态链接库(DLL)的函数或方法,实现特定功能的过程。相对于静态链接库,动态调用DLL具有更加灵活和高效的特点。 在Windows平台上,可以使用Win32 API提供的LoadLibrary、GetProcAddress等函数实现动态调用DLL。LoadLibrary函数用于加载DLL文件,并返回一个句柄,可以通过这个句柄获取DLL导出函数的地址。而GetProcAddress函数则可以根据函数名称获取函数地址,即导出函数表的函数指针。 使用动态调用DLL,可以动态地载入需要的库,从而减少了程序的运行时内存开支,而且可以实现不同版本动态链接库的切换。此外,动态调用DLL还可以实现模块化编程,使程序的各个部分之间更加独立和可重用。 需要注意的是,在使用动态调用DLL时,一定要确保DLL文件的正确性和可靠性。因为DLL文件的损坏或恶意篡改可能会导致程序崩溃或者安全漏洞。因此,在使用动态链接库时,务必进行严格的文件验证和权限控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值