文章

VS下dll的生成和使用

1.前言

我在去年其实写过一篇关于dll的博客,但当时只是简单记录了过程,今年在给新员工出dll题目时,发现很多人对dll不太熟悉,所以想再写一篇博客,详细讲讲。

dll是什么呢?它是微软在Windows平台下的动态链接库,我们经常见到Windows软件安装目录有一堆的dll,你可以理解为各个模块,就是我软件如果用到哪个功能了,我再调用这个功能模块,这样不会让软件exe看起来很大。对应的有静态链接库,静态链接库则是把各种实现全部塞进exe里面,如果有一个函数被其他地方调用,这个函数就会被复制好几次。

2.在VS下创建dll

通过创建项目,选择动态链接库,VS会默认给你生成一堆文件,其中有个文件叫做dllmain,函数里面是这样的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.怎么写导出函数

正常来说,你是需要这样写

1
extern "C" __declspec(dllexport) void myfunc();

因为C和C++的编译方式不同,C++支持函数重载而C不支持,所以在编译后,C++的函数名很有可能不再是现在的名字,而C不会是这种情况,名字不同时,将来调用就会出错。于是extern “C”就是让编译器对它按照C语言的编译。

至于__declspec(dllexport)你可以理解成个固定语法,这个你可以在微软官网找到详细的解释,我就不放了,简单理解就是,加了这个是让这个函数可以被导出,让外部来用它

上面说的这个是一般写法,但现在VS其实默认生成是这样的

1
FIRSTDLL_API int myfunc(void);

其中FIRSTDLL_API是个宏,它一般是你这个项目名字的大写,宏是这样的

1
2
3
4
5
#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

这时候直接去你源代码里调用这个函数就行了

本文由作者按照 CC BY 4.0 进行授权