您的位置:首页 > 编程语言 > C语言/C++

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

2009-06-21 15:51 579 查看
Windows Via C/C++ 读书笔记 13
动态链接库基础DLL Basics

1. Overview

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



左边的树是DLL文件的生成过程:
1 编写头文件,包含了需要导出的函数 变量 类型等。
2 编写CPP文件,包含了函数的实现。
3 compile出obj文件。
4-5 Link出一个.dll和一个.lib文件。.dll文件被.exe文件调用。.lib文件只在.exe文件通过隐式调用方式调用DLL文件的时候有用。本章的例子就是个隐式链接方式,还有一种是显示链接通过API在程序运行时动态加载的方式,后面DLL高级部分会讲到。Step9,exe链接的时候讲这个lib文件为什么有用。Lib文件包含了dll导出的函数 变量等信息,并包含这个dll文件的名字,当exe链接的时候,它知道它用到的函数不是自己实现的,是需要从外部导入的,通过lib文件可以知道哪些函数是从外部导入的,从哪个dll文件导入。
右边树是exe文件编译链接过程。
前三步和dll文件类似,和普通exe文件的完全相同。
区别是:step6,头文件和DLL导出声明的头文件是同一个文件,因此在compile的时候,exe程序已经完全知道了要调用的函数名称,数据类型等信息。这些信息是compile出obj文件必需也仅需的。
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: