当一个模块(如可执行文件)用到了一个DLL的函数或者变量的时候,会牵涉到许多文件和组件。为了便于讨论,我们将一个dll中导入函数和变量的模块称为“可执行模块”,将导出函数和变量一个供其他可执行文件使用的模块成为“DLL模块”,dll模块也可以导入一些包含其他dll模块中的函数和变量。
构建dll,需要以下步骤:
1. 必须创建一个头文件,在其中包含我们想要在DLL中导出的函数原型,结构以符号。为了构建该DLL,dll中的所有源文件需要包含该头文件。
2. 创建C/C++源文件来实现想要在DLL模块中淡出的函数和变量。
3. 当构建dll模块的时候,编译器会对每个源文件进行处理产生一个obj文件,(每个源文件,对应一个obj模块)
4. 当所有的obj模块创建完毕后,连接器会将所有的.obj模块内容合并,产生一个单独的dll映像文件。这个映像文件或者模块,包含dll中所有的二进制代码以及全局/静态变量。为了执行可执行模块快,这个文件时必须的。
5. 如果连接器检测到DLL的源文件输出少了一个函数或者变量,那么连接器还有生成一个lib文件。这个lib文件非常小,这是因为他并不包含任何函数或者变量。她它只是列出了所有被导出的函数和变量的负号名。为了构建可执行模块,这个模块是必须的。
一旦构建了dll模块,我们就可以通过下列步骤构建可执行模块
1. 在所有的引用了dll的模块,变量,必须包含有dll的开发者所创建的头文件。
2. 创建C++源文件来实现想要的包含在可执行模块的函数和变量。当然,代码可以引用在dll的头文件中的定义的函数和变量。
3. 在构建可执行模块时候,编译器会对每个源文件进行处理并产生一个.obj文件。
4. 当所有的obj都创建完毕后,连接器会将所有的obj模块的内容合并,产生一个单独的可执行文件,这个映像文件包含了可执行文件中的所有二进制代码以及全局静态变量。该可执行文件还包含一个导入段,其中列出了它需要的dll模块的名称。
5. 加载程序先为新的进程创建一个虚拟的地址空间,并将可执行模块映射到新的地址空间中。
一旦加载程序将可执行模块和所有的dll模块映射到进程的地址空间之后,进程的主线程可以开始执行,这样引用程序就能够运行了。