MFC|导出dll之导出函数

834 阅读4分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

在C++中有这样一个导出功能,我觉得还真是方便,当开发大型项目时,可以将单独的页面处理、逻辑处理分出去,使得我们的程序可以模块化。

今天就为大家介绍关于MFC框架下导出dll的使用吧,首先从简单的导出函数说起。

在制作导出库时,有人喜欢使用导出类,觉得这样层次明显,有人喜欢用导出函数,觉得使用方便,其实各有各的好处,那么什么情况下使用导出函数比较好呢

1:进行逻辑计算的操作,举一个简单的例子:加法、减法、乘法、除法等。这些都是单独的个体,每个函数之间没有任何联系。

2:用于控制指令操作,比如说:开始、结束、打开、关闭。与硬件简单的交互指令时,导出函数会更加方便。

总而言之,能用一个函数代表一个单独的功能,并且与其它函数不关联时,使用导出函数的情况比较多。

下面我就来着重讲解下MFC框架下导出函数的基础操作!

开发环境:VS2017 x64

导出函数dll制作

1:创建导出项目

新建项目,记得选择MFC动态链接库

MFC动态链接库.png

导出库的名称我们可以自己定义,假设:QOperationDll

点击确定后,出现下面的页面,选择“使用共享MFC DLL的常规 DLL”,因为在导出函数中不涉及到页面效果,所以使用默认类型就可以了。对于导出带页面的dll,后续我会逐步介绍的~

共享dll选择.png 点击确定后,一个简单的导出类就制作完成啦~

2:简单应用

创建完成后,这里简单举例说明,假设导出一个计算两个数值之和的函数,如下:

int CalcAddNum(int num1, int num2);

将该函数作为导出函数,那么我们该如何操作呢?

2.1:定义导出宏

在这里需要注意的是:导出函数的宏定义与导出类的宏定义是有区别的!

#define INTERREXPORT_BUILD
#if defined	(INTERREXPORT_BUILD)
#	 define	_InterrExport	extern "C" _declspec(dllexport)
#else
#	 define	_InterrExport  extern "C" _declspec(dllimport)
#endif

其中使用这句代码:#define INTERREXPORT_BUILD,有些人制作dll过程中会漏掉,不过当时漏掉也没关系,只要在使用dll的工程中属性配置上就可以了。这是一个隐藏、最容易出错的地方。在程序中有可能因为这句代码导致你在使用工程中一直加载不上dll,这里,大家需要引起注意喽~

2.2:导出函数实现

.h中声明

_InterrExport int CalcAddNum(int num1, int num2);

.cpp中实现

_InterrExport int CalcAddNum(int num1, int num2)
{
	return num1 + num2;
}

很简单吧!这样一个简单的导出函数就制作完成了。

工程中应用导出函数

当前导出dll只是做了函数导出,不需要在使用工程中添加.h以及.cpp文件,哪个项目使用dll,只需要在工程中配置dll就行啦~

1:程序中加载dll库

这是很多人在加载dll时最容易忽略的地方了!!!

如果不在同一路径下,很容易在代码中加载dll时,返回nullptr

HINSTANCE handle = LoadLibrary(L"COperationDll_d.dll");

handle==nullptr时,很大程度上是因为dll路径与exe路径不匹配造成的!

2:注册导出函数

加载了导出库之后,在开发程序中,使用哪个导出函数,就需要对该函数进行注册,这里还拿上面CalcAddNum函数讲解。

//回调函数:计算两个数之和
typedef int(*AddNum)(int num1, int num2);
AddNum pFuncAddNum = nullptr;

提前声明回调函数指针,下一步是要注册该函数指针

pFuncAddNum = (AddNum)GetProcAddress(handle, "CalcAddNum");

当pFuncAddNum不是空指针时,说明注册成功了。

有些同学在第一次使用导出函数时会遇到导出库句柄是有效的,为什么注册的函数指针就是nullptr呢?

一般这个问题90%的可能出在回调函数的宏定义上,所以在注册回调函数时,一定要区分回调类与回调函数的注册方法。

好了,到这里简单的导出函数功能就更新结束喽~

我是中国好公民st,一名C++开发程序猿~

本文正在参加「金石计划 . 瓜分6万现金大奖」