📄 chap13.html
字号:
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">本节以非</FONT><FONT SIZE=3>MFC DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>为例来讲解</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的结构和导出方法,并介绍创建和使用</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的方法和步骤。</P>
</FONT><FONT FACE="Arial"><P>13.2.1 DLL</FONT><FONT FACE="黑体" LANG="ZH-CN">的结构和导出方式</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件和</FONT><FONT SIZE=3>EXE</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件都属于可执行文件,不同的是</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件包括了一个导出表,导出表中给出了可以从</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中导出的所有函数的名字。外部可执行程序只能访问包括在</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的导出表中的函数,</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中的其它函数是私有的,不能为外部可执行程序所访问。</P>
<P ALIGN="JUSTIFY">可以使用</FONT><FONT SIZE=3>Visual C++</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>提供的</FONT><FONT SIZE=3>DUMPBIN</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>实用程序(可以在</FONT><FONT SIZE=3>DevStudio\VC\bin</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>目录下找到这个工具)来查看一个</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件的结构。举一个例子,如果需要查看</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件</FONT><FONT SIZE=3>msgbox.dll</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>(我们将在本小节的后续内容中创建该</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>)的导出表,可以在命令提示符下键入下面的命令:</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>>dumpbin /exports msgbox.dll</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">运行结果如下:</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>Microsoft (R) COFF Binary File Dumper Version 5.00.7022</P>
<P>Copyright (C) Microsoft Corp 1992-1997. All rights reserved.</P>
<P>Dump of file msgbox.dll</P>
<P>File Type: DLL</P>
<P> Section contains the following Exports for MSGBOX.dll</P>
<P> 0 characteristics</P>
<P> 351643C3 time date stamp Mon Mar 23 19:13:07 1998</P>
<P> 0.00 version</P>
<P> 1 ordinal base</P>
<P> 1 number of functions</P>
<P> 1 number of names</P>
<P> ordinal hint name</P>
<P> 1 0 MsgBox (00001000)</P>
<P> Summary</P>
<P> 7000 .data</P>
<P> 1000 .idata</P>
<P> 2000 .rdata</P>
<P> 2000 .reloc</P>
<P> 17000 .text</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">由上面的结果得知,</FONT><FONT SIZE=3>msgbox.dll</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中仅包括了一个导出函数</FONT><FONT SIZE=3>MsgBox()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。</P>
<UL>
</FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"><LI>注意:</LI></P>
</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"><LI>仅仅知道导出函数的名称并不足以从</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>中导出该函数。若在应用程序中使用显式链接(</FONT><FONT SIZE=3>link explicitly</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>),至少还应该知道导出函数的返回值的类型以及所传递给导出函数的参数的个数、顺序和类型;若使用隐含链接(</FONT><FONT SIZE=3>link implicitly</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>),必须有包括导出函数(或类)的定义的头文件(</FONT><FONT SIZE=3>.H</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>文件)和引入库(</FONT><FONT SIZE=3>import library</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>.LIB</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>文件),这些文件是由</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>的创建者所提供的。关于显式链接和隐含链接,将在本章的“</FONT><FONT SIZE=3>13.2.2 </FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>链接应用程序到</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="楷体_GB2312" LANG="ZH-CN" SIZE=3>”小节中讲述。</LI></P></UL>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">从</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中导出函数有两种方法:</P>
<UL>
<P ALIGN="JUSTIFY"><LI>在创建</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>时使用模块定义(</FONT><FONT SIZE=3>module DEFinition</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,</FONT><FONT SIZE=3>.DEF</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>)文件。</LI></P>
<P ALIGN="JUSTIFY"><LI>在定义函数时使用关键字</FONT><FONT SIZE=3>__declspec(dllexport)</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。</LI></P></UL>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">下面我们通过一个简单的例子来分别说明两种方法的使用。在这个例子中,我们将创建一个只包括一个函数</FONT><FONT SIZE=3>MsgBox()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,函数</FONT><FONT SIZE=3>MsgBox()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>用来显示一个消息框,它和</FONT><FONT SIZE=3>Win32 API</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>函数</FONT><FONT SIZE=3>MessageBox()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的功能是一样,只不过在函数</FONT><FONT SIZE=3>MsgBox()</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中,不需要指定消息的父窗口,而且可以缺省其它所有的参数。</P><DIR>
</FONT><FONT FACE="Arial" SIZE=3><P>(1)	</FONT><FONT FACE="黑体" LANG="ZH-CN" SIZE=3>使用模块定义文件</P></DIR>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">模块定义文件是一个文本文件,它包括了一系列的模块语句,这些语句用来描述</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的各种属性,典型的,模块语句定义了</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中所导出的函数的名称和顺序值。</P>
<P ALIGN="JUSTIFY"></P>
<P ALIGN="JUSTIFY">在讲解模块定义文件之前,我们先创建一个</FONT><FONT SIZE=3>Win32 Dynamic-Link Library</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>工程。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">1.	</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>在</FONT><FONT SIZE=3>Microsoft Developer Studio</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中选择</FONT><FONT SIZE=3>File</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>菜单下的</FONT><FONT SIZE=3>New</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>命令,在</FONT><FONT SIZE=3>Projects</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>选项卡中选择</FONT><FONT SIZE=3>Win32 Dynamic-Link Library</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,并为工程取一个名字,如</FONT><FONT SIZE=3>msgbox</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。单击</FONT><FONT SIZE=3>OK</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>后,</FONT><FONT SIZE=3>Visual C++</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>创建一个</FONT><FONT SIZE=3>Win32 DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的空白工程,必须手动的将所需要的文件添加到工程中。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">2.	</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>单击</FONT><FONT SIZE=3>Project</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>菜单下的</FONT><FONT SIZE=3>Add To Project</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>子菜单下的</FONT><FONT SIZE=3>New</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>命令,在</FONT><FONT SIZE=3>Files</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>选项卡中选择</FONT><FONT SIZE=3>Text File</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,在</FONT><FONT SIZE=3>File</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文本框中输入</FONT><FONT SIZE=3>DEF</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件名,如</FONT><FONT SIZE=3>msgbox.def</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">3.	</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>双击</FONT><FONT SIZE=3>Workspace</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>窗口的</FONT><FONT SIZE=3>FileView</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>选项卡中的</FONT><FONT SIZE=3>msgbox.def</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>节点,在</FONT><FONT SIZE=3>msgbox.def</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件中输入下面的内容:</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=1><P>LIBRARY MSGBOX</P>
<P>DESCRIPTION "一个DLL的简单例子"</P>
<P>EXPORTS</P>
<P>	MsgBox	@1</P>
</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3><P ALIGN="JUSTIFY">在</FONT><FONT SIZE=3>DEF</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件中的第一条语句必须是</FONT><FONT SIZE=3>LIBRARY</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>语句,该语句表明该</FONT><FONT SIZE=3>DEF</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>文件属于一个</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,在</FONT><FONT SIZE=3>LIBRARY</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>之后是</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的名称,这个名称在链接时将放到</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的引入库中。</P>
</FONT><FONT SIZE=3><P ALIGN="JUSTIFY">EXPORTS</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>语句下列出了</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>的所有导出函数以及它们的顺序值。函数的顺序值不是必须的,在指定导出函数的顺序值时,我们在函数名后跟上一个</FONT><FONT SIZE=3>@</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>符号和一个数字,该数字即导出函数的顺序值。如果在</FONT><FONT SIZE=3>DEF</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中指定了顺序值,它必须不小于</FONT><FONT SIZE=3>1</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>,且不大于</FONT><FONT SIZE=3>DLL</FONT><FONT FACE="宋体" LANG="ZH-CN" SIZE=3>中所有导出函数的数目。</P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -