动态链接库(dll) - 第一个DLL程序

本文章转载自C语言中文网


DLL 程序的入口函数是 DllMain(),就像 DOS 程序的入口函数是 main()、Win32 程序的入口函数是 WinMain() 一样。

DllMain() 函数的原型为:

BOOL APIENTRY DllMain(
    HANDLE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
);

其中:

  • hModule 表示本DLL程序的句柄。
  • ul_reason_for_call 表示DLL当前所处的状态;
    例如:DLL_PROCESS_ATTACH表示DLL刚刚被加载到一个进程中DLL_PROCESS_DETACH表示DLL刚刚从一个进程中卸载。
  • lpReserved 表示一个保留参数,目前已经很少使用。

使用vs2015简历一个DLL工程,代码如下:
dlldemo.cpp

#include <windows.h>
#include <stdio.h>

extern "C" __declspec(dllexport) int add(int a, int b) {
    return a + b;
}
extern "C"  __declspec(dllexport)int sub(int a, int b) {
    return a - b;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        printf("已链接上DllDemo.dll了");
        break;
    case DLL_THREAD_ATTACH:
        printf("DLL_THREAD_ATTACH");
        break;
    case DLL_THREAD_DETACH:
        printf("DLL_THREAD_DETACH");
        break;
    case DLL_PROCESS_DETACH:
        printf("已跟DllDemo.dll断开链接了");
        break;
    }
    return TRUE;
}

然后利用Build命令生成DllDemo这一动态链接库程序。之后,在该工程的Debug目录下, 可以看到有一个DllDemo.dll文件和一个DllDemo.lib文件,这就是生成的动态链接库文件。

读者要记住,应用程序如果想要访问某个DLL中的函数,那么该函数必须是已经被导出的函数。为了导出一些函数,需要在函数前面添加标识符 _declspec(dllexport)。

在命令行界面下,cd 到工程目录下的debug目录,输入dumpbin -exports DllDemo.dll 命令,然后回车,即可查看DLL中的导出函数,如下图:
这里写图片描述

注意红色方框标出的信息:

ordinal hint  RVA   name
  1   0  000110D7  add
  2   1  000110DC  sub

在这段信息中:  

  • “ordinal” :列出的信息 ‘1’ 和 ‘2’ 是导出函数的序号;
  • “hint” :列出的数字是提示码,该信息不重要;
  • “RVA” :列出的地址值是导出函数在DLL模块中的位置,也就是说,通过该地址值,可以在DLL中找到它们;
  • “name” :列出的是导出函数的名称;

将 add 函数前面的 __declspec(dllexport) 标识符去掉,再次编译 dllDemo 工程,然后执行 dumpbin -exports DllDemo.dll 命令,输出如下图所示:
这里写图片描述
可以看到,add 函数已经不是导出函数了。

打开项目目录下的Debug目录,发现有 DllDemo.dll 和 DllDemo.lib 两个文件。上节已经说过,.lib 文件包含DLL导出的函数和变量的符号名,.dll 文件才包含实际的函数和数据。主程序调用 DLL 需要这两个文件,下节会讲解如何使用。

注意: DllMain() 函数在DLL程序载入和卸载时执行,可以用来做一些初始化和清理的工作,如果仅仅是向外暴露函数,就可以省略 DllMain() 函数。但是如果有 DllMain() 函数,就一定要 #include <base.h> 或 #include <windows.h>。

例如,上面DLL如果只想暴露 add() 和 sub() 函数,而不想进行其他操作,那么可以这样写:
dlldemo.cpp

#include <stdio.h>

extern "C" __declspec(dllexport) int add(int a, int b) {
    return a + b;
}
extern "C"  __declspec(dllexport)int sub(int a, int b) {
    return a - b;
}

注意:extern “C” 避免名字粉碎,因为这里不是使用C来写,而是使用C++,加上extern “C”后,会指示编译器这部分代码按C语言的进行编译(强制编译器不要修改你的函数名),而不是C++的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值