Windows Via C/C++ 读书笔记 13 动态链接库基础DLL Basics

Windows Via C/C++ 读书笔记 13 

动态链接库基础DLL Basics

1. Overview

本章讲DLL概念(比一些教程仔细得多),实现方式,并给一个简单的DLL例子说明代码如何构建。废话少说,先上图。这张图说明了一个DLL由编写到链接、被调用的全部过程。看这篇文章前,你至少要知道什么是compile,什么是link,都干了些啥。

DLL process

左边的树是DLL文件的生成过程:

编写头文件,包含了需要导出的函数 变量 类型等。

编写CPP文件,包含了函数的实现。

3 compileobj文件。

4-5 Link出一个.dll和一个.lib文件。.dll文件被.exe文件调用。.lib文件只在.exe文件通过隐式调用方式调用DLL文件的时候有用。本章的例子就是个隐式链接方式,还有一种是显示链接通过API在程序运行时动态加载的方式,后面DLL高级部分会讲到。Step9exe链接的时候讲这个lib文件为什么有用。Lib文件包含了dll导出的函数 变量等信息,并包含这个dll文件的名字,当exe链接的时候,它知道它用到的函数不是自己实现的,是需要从外部导入的,通过lib文件可以知道哪些函数是从外部导入的,从哪个dll文件导入。

右边树是exe文件编译链接过程。

前三步和dll文件类似,和普通exe文件的完全相同。

区别是:step6,头文件和DLL导出声明的头文件是同一个文件,因此在compile的时候,exe程序已经完全知道了要调用的函数名称,数据类型等信息。这些信息是compileobj文件必需也仅需的。

Step 9,链接的时候必须链入lib文件,否则程序在link的过程中,会报无法找到函数实现的错误。因为link的过程会遍历所有的obj,尝试寻找所有函数的实现部分。而这些函数都是从外部导入的,肯定是找不到的。当它看到lib文件后,会得知这些函数的实现信息,"哦,在dll中,不链接到exe代码段,执行的时候从dll中映射过来。"

Step10,程序启动的时候寻找dll文件(寻找dll文件的顺序各个操作系统微有不同,见msdn dll path)。找到后把代码和变量映射到自己的地址空间,如果找不到,会弹一个窗口,"xx.dll找不到!"。它为什么会知道哪个dll找不到?Lib文件告诉它了。

2. DLL与进程地址空间

进程在调用DLL之前,需要把dll文件映射到自己的地址空间中,然后就像调用自己的代码一样调用dll。前面《Windows Via C/C++ 读书笔记 11 Memory-Mapped Files(内存映射文件)》讲了这部分内容。虽然dll只会被加载一次到Page File,然后被多个进程共享,但是它们之间的静态变量是不会共享的(copy-on-write方式实现,见笔记11)。这是dll编写者最常见的问题。

3. 构建一个简单DLL

注意MYLIBAPI的定义,其实在h文件定义一次就足够了。

extern "C" 表示生成的函数命名不要用c++的方式,c++会修改命名。不然,这个dll只能被c++程序使用,而不能被其它语言编写的程序使用。

__declspec(dllimport) 告知dll编译器需要导出,compiler会在obj文件里面加入这些信息,link读到这些信息然后生成dll;也告知exe编译器,这些函数在dll中找到,不要在obj文件中找。

dumpbin工具可以查看dll文件的导出段(export section),使用-exports开关。Dumpbin使用见笔记11

/***************************************************************************

Module:  MyLib.h

***************************************************************************/

#ifdef MYLIBAPI

// MYLIBAPI should be defined in all of the DLL's source

// code modules before this header file is included.

// All functions/variables are being exported.

#else

// This header file is included by an EXE source code module.

// Indicate that all functions/variables are being imported.

#define MYLIBAPI extern "C" __declspec(dllimport)

#endif

// Define any data structures and symbols here.

// Define exported variables here. (NOTE: Avoid exporting variables.)

MYLIBAPI int g_nResult;

// Define exported function prototypes here.

MYLIBAPI int Add(int nLeft, int nRight);

// End of File /

In each of your DLL's source code files, you should include the header file as follows:

/***************************************************************************

Module: MyLibFile1.cpp

***************************************************************************/

// Include the standard Windows and C-Runtime header files here.

#include <windows.h>

// This DLL source code file exports functions and variables.

#define MYLIBAPI extern "C" __declspec(dllexport)

// Include the exported data structures, symbols, functions, and variables.

#include "MyLib.h"

// Place the code for this DLL source code file here.

int g_nResult;

int Add(int nLeft, int nRight) {

   g_nResult = nLeft + nRight;

   return(g_nResult);

}

// End of File /

我的测试文件打印出的dumpbin结果,可以看到导出的变量g_nResult和函数Add

E:/projects/dlltest/Debug>dumpbin -exports dlltest.dll

Microsoft (R) COFF/PE Dumper Version 8.00.50727.762

Copyright (C) Microsoft Corporation.  All rights reserved.

Dump of file dlltest.dll

File Type: DLL

  Section contains the following exports for dlltest.dll

    00000000 characteristics

    4A3B8423 time date stamp Fri Jun 19 20:27:15 2009

        0.00 version

           1 ordinal base

           2 number of functions

           2 number of names

    ordinal hint RVA      name

          1    0 000110BE Add = @ILT+185(_Add)

          2    1 00017150 g_nResult = _g_nResult

  Summary

        1000 .data

        1000 .idata

        2000 .rdata

        1000 .reloc

        1000 .rsrc

        4000 .text

       10000 .textbss

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值