1.前言
我在去年其实写过一篇关于dll的博客,但当时只是简单记录了过程,今年在给新员工出dll题目时,发现很多人对dll不太熟悉,所以想再写一篇博客,详细讲讲。
dll是什么呢?它是微软在Windows平台下的动态链接库,我们经常见到Windows软件安装目录有一堆的dll,你可以理解为各个模块,就是我软件如果用到哪个功能了,我再调用这个功能模块,这样不会让软件exe看起来很大。对应的有静态链接库,静态链接库则是把各种实现全部塞进exe里面,如果有一个函数被其他地方调用,这个函数就会被复制好几次。
2.在VS下创建dll
通过创建项目,选择动态链接库,VS会默认给你生成一堆文件,其中有个文件叫做dllmain,函数里面是这样的
代码语言:javascript复制BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
这个函数其实是动态链接库的入口,就像C 的入口是main一样,三个参数,你只用知道第二个参数是说调用的原因即可。
根据不同的调用原因,所以执行代码不同
DLL_PROCESS_ATTACH 是加载
DLL_PROCESS_DETACH 是卸载
中间两个是thread有关的
其中APIENTRY是一个宏,进去后发现是WINAPI,WINAPI也是宏,进去后发现是__stdcall
3.怎么写导出函数
正常来说,你是需要这样写
代码语言:javascript复制extern "C" __declspec(dllexport) void myfunc();
因为C和C 的编译方式不同,C 支持函数重载而C不支持,所以在编译后,C 的函数名很有可能不再是现在的名字,而C不会是这种情况,名字不同时,将来调用就会出错。于是extern “C”就是让编译器对它按照C语言的编译。
至于__declspec(dllexport)你可以理解成个固定语法,这个你可以在微软官网找到详细的解释,我就不放了,简单理解就是,加了这个是让这个函数可以被导出,让外部来用它
上面说的这个是一般写法,但现在VS其实默认生成是这样的
代码语言:javascript复制FIRSTDLL_API int myfunc(void);
其中FIRSTDLL_API是个宏,它一般是你这个项目名字的大写,宏是这样的
代码语言:javascript复制#ifdef FIRSTDLL_EXPORTS
#define FIRSTDLL_API __declspec(dllexport)
#else
#define FIRSTDLL_API __declspec(dllimport)
#endif
你一看,其实还是我上面说的__declspec(dllexport)
一般你函数声明有__declspec(dllexport)时,函数实现便写不写都行了
这时候你就生成解决方案吧
4.如何使用生成的dll
生成后,你需要用到是dll和lib
1.dll放到你现在项目(也就是需要用到dll的项目)的exe同目录下
2.头文件放到你的源代码下,并且在你的源代码中添加这个头文件
3.去链接器里,把附加库目录写成你的lib在的目录,附加依赖项写你的lib名字,比如firstdll.lib
这时候直接去你源代码里调用这个函数就行了