DLL动态链接库的创建与使用

Posted jawide

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DLL动态链接库的创建与使用相关的知识,希望对你有一定的参考价值。

?

动态链接库英文为DLL,是Dynamic Link Library的缩写。DLL是一个包含可由多个程序,同时使用的代码和数据的库 --------------百度百科

?

下面我们使用vs2010创建一个可供win32程序使用的dll

?

  1. 打开vs2010,点击新建项目
    技术图片

    ?

  2. 新建一个win32项目
    技术图片

?

?

  1. 点击下一步
    技术图片

    ?

  2. 新建一个空的dll项目
    技术图片
  3. 右键源文件,添加,新建项
    技术图片

    ?

  4. 新建一个c文件
    技术图片



  5. 同样的在头文件里新建一个h文件
    技术图片
  6. 然后就可以开始写代码了



    每一个dll都有一个入口函数,这个入口函数叫做 DLLMain
    这个东西咱暂时用不到,就先不写了,如果你生成的是标准的dll文件,这个入口函数就会出现在你的源代码中。

    ?

    然后就可以开始写函数了,在写函数之前,先介绍一下dll中的规则

    ?

    1. 函数前面要加上修饰符 如__declspec(dllexport) 他的意思是 declear spece dll export 声明这是一个导出的dll函数。
    2. windows要求dll函数要加上修饰符CALLBACK (但这只是windows要求,dll要是不是给windows应用程序用的就不用加上这个)。
    3. 用extern "c"来表明使用c语言的规则解释函数

    ?

    函数:

__declspec(dllexport) void GiaoWarningA()

{

????MessageBoxA(NULL,"giao","warning",MB_OK);

????return;

}

?

__declspec(dllexport) void GiaoWarningW()

{

????MessageBoxW(NULL,L"giao",L"warning",MB_OK);

????return;

}

一般winapi中的函数都有两个版本,一个是ascii码版本,一个是unicode版本,windows使用宏来自动选择,例如

//编码判断

#ifdef UNICODE

#define GiaoWarning GiaoWarningA

?

#else

#define GiaoWarning GiaoWarningW

?

#endif

我们也可以借鉴这种思想,来自动选择是否加上extern "C"

?

例如

//语言判断

#ifdef __cplusplus

#define EXPORT extern "C" __declspec (dllexport)

#else

#define EXPORT __declspec (dllexport)

#endif

?

了解了这些我们就可以开始写我们的头文件了

头文件giao.h

//语言判断

#ifdef __cplusplus

#define EXPORT extern "C" __declspec (dllexport)

#else

#define EXPORT __declspec (dllexport)

#endif

?

//函数声明

EXPORT void CALLBACK GiaoWarningA();

EXPORT void CALLBACK GiaoWarningW();

?

//编码判断

#ifdef UNICODE

#define GiaoWarning GiaoWarningA

?

#else

#define GiaoWarning GiaoWarningW

?

#endif

注意这三块代码我摆放的顺序

  1. 语言判断 声明了EXPORT宏
  2. 函数声明????使用了EXPORT宏
  3. 编码判断 使用函数名创建了统一函数名的宏

?

另外还有一点,在函数声明中EXPORT void CALLBACK的顺序可别弄乱了

EXPORT void CALLBACK GiaoWarningA();

?

源文件giao.c

#include "giao.h"

#include <Windows.h>

?

EXPORT void CALLBACK GiaoWarningA()

{

????MessageBoxA(NULL,"giao","warning",MB_OK);

????return;

}

?

EXPORT void CALLBACK GiaoWarningW()

{

????MessageBoxW(NULL,L"giao",L"warning",MB_OK);

????return;

}

?

源文件中的函数原型与头文件中的一毛一样

还有就是头文件中要包含giao.h和函数用到的头文件

?

  1. 然后右键项目,点击生成
    技术图片

    ?

  2. 右键giao点击打开所在的文件夹
    技术图片
  3. 返回到上一级目录
    共有三个重要的文件 giao.h giao.lib giao.dll
    技术图片

    ?

  4. 进入这一级的Debug目录
    技术图片

?

?

  1. 然后就找到了全部的三个文件
    技术图片

    ?

  2. 如何使用动态链接库
    使用动态链接库的方法有两种,一种是启动时加载,一种是运行时加载

    我们先来将如何在 启动时加载链接库

    ?

  3. 启动时加载链接库
    我们依然还是新建一个win32项目



    技术图片

    ?

  4. 直接点击完成
    技术图片
  5. 右键打开项目所在文件夹
    技术图片
  6. 将之前的giao.h giao.lib giao.dll全都复制到这里
    技术图片
  7. 添加头文件 giao.h

    技术图片

    技术图片

    ?

    技术图片

?

  1. 添加链接库导入文件 giao.lib
    技术图片

    技术图片


    技术图片
    注意lib和dll的名字是你dll项目的名字,而h文件的名字是你创建的时候指定的,不要弄混了,还有这里千万不要写成wdnmd.dll要不然会出错,而且编译器也发现不了。

    ?

  2. 开始使用

技术图片
我是把函数放在WM_PAINT里了,你也可以放在其他地方,

?

  1. 运行结果
    技术图片

?

  1. 运行时加载动态链接库
    我们会用到两个函数,LoadLibrary,GetProcAddress

    功能是加载动态链接库,获取函数地址

  2. 定义一个宏,创建两个变量
    因为我们会用到函数地址,就要用函数指针来保存这个函数地址
    而且因为我们要对GetProcAddress返回的地址进行强制类型转换,所以我们要定义一个宏来代替一个函数指针的类型

    还有一个实例句柄用来操作动态链接库

????typedef void (*FUC)();

????FUC fuc;

????HINSTANCE hlibrary;

然后

hlibrary = LoadLibraryA("wdnmd.dll");

fuc = (FUC)GetProcAddress(hlibrary,"GiaoWarningA");

fuc();

?

这里我遇到了一些问题,GetProcAddress的返回值一直都是NULL,好像是函数名有问题。

找到了一些解决的方法,但也不是太好

?

关于__stdcall????????导出的函数名为: _函数名@0????????(0为参数所占的总字节数)

__fastcall????????导出的函数名为: @函数名@0????????(同上)

__cdel????????导出的函数名为: 函数名

啥都不加????????导出的函数名为: 函数名

windows要求的CALLBACK其实就是这个__stdcall,所以可以按照他的导出格式,去调用函数。如 fuc = (FUC)GetProcAddress(hlibrary,"_GiaoWarningA@0");

以上是关于DLL动态链接库的创建与使用的主要内容,如果未能解决你的问题,请参考以下文章

VC++程序设计与应用--动态链接库

LINUX系统中动态链接库的创建与使用

动态链接库与静态链接库的区别

VS2019 C++动态链接库的创建使用

动态链接库的编写及使用

如何用VS2010编写动态链接库DLL