📄 chap9_3.htm
字号:
<p>{</p>
<p>// Construction</p>
<p>public:</p>
<p>CTestDlg(CWnd* pParent = NULL); // standard constructor</p>
<p>protected:</p>
<p>void LoadDLL();</p>
<p>//......</p>
<p>}</p>
<p></font><font SIZE="3">然后修改</font><font FACE="Times New Roman" SIZE="3">testdlg.cpp</font><font SIZE="3">,修改后如清单</font><font FACE="Times New Roman" SIZE="3">9.5</font><font SIZE="3">。<b></p>
<p>清单</font><font FACE="Times New Roman" SIZE="3">95. TestDlg.cpp</font><font SIZE="3">文件</font></b><font FACE="Times New Roman" SIZE="3"></p>
<p>// TestDlg.cpp : implementation file</p>
<p>//</p>
<p>#include "stdafx.h"</p>
<p>#include "Test.h"</p>
<p>#include "TestDlg.h"</p>
<p>//#include "mymath.h" //</font><font SIZE="3">注释掉</font><font FACE="Times New Roman" SIZE="3">mymath.h</font><font SIZE="3">头文件</font><font FACE="Times New Roman" SIZE="3"></p>
<p>#ifdef _DEBUG</p>
<p>#define new DEBUG_NEW</p>
<p>#undef THIS_FILE</p>
<p>static char THIS_FILE[] = __FILE__;</p>
<p>#endif</p>
<p>//The instance of the Mymaths.DLL library</p>
<p>HINSTANCE ghMathsDLL=NULL;</p>
<p>//declare the Summary() function from the Mymaths.DLL libray.</p>
<p>typedef int (*SUMMARY)(int);</p>
<p>SUMMARY Summary;</p>
<p>//declare the Factorial() function from</p>
<p>//the Mymaths.DLL library.</p>
<p>typedef int (*FACTORIAL)(int);</p>
<p>FACTORIAL Factorial;</p>
<p>/////////////////////////////////////////////////////////////////////////////</p>
<p>// CAboutDlg dialog used for App About</p>
<p>class CAboutDlg : public CDialog</p>
<p>{</p>
<p>//...</p>
<p>};</p>
<p>//CAboutDlg</font><font SIZE="3">的一些成员函数定义</font><font FACE="Times New Roman" SIZE="3"></p>
<p>//CTestDlg</font><font SIZE="3">的一些成员函数定义</font><font FACE="Times New Roman" SIZE="3"></p>
<p>void CTestDlg::OnSum() </p>
<p>{</p>
<p>// TODO: Add your control notification handler code here</p>
<p>LoadDLL();</p>
<p>int nSum=Summary(10);</p>
<p>CString sResult;</p>
<p>sResult.Format("Sum(10)=%d",nSum);</p>
<p>AfxMessageBox(sResult);</p>
<p>}</p>
<p>void CTestDlg::OnFactorial() </p>
<p>{</p>
<p>// TODO: Add your control notification handler code here</p>
<p>LoadDLL();</p>
<p>int nFact=Factorial(10);</p>
<p>CString sResult;</p>
<p>sResult.Format("10!=%d",nFact);</p>
<p>AfxMessageBox(sResult);</p>
<p>}</p>
<p>void CTestDlg::LoadDLL()</p>
<p>{</p>
<p>//</font><font SIZE="3">如果</font><font FACE="Times New Roman" SIZE="3">DLL</font><font SIZE="3">已经载入,则返回</font><font FACE="Times New Roman" SIZE="3"></p>
<p>if(ghMathsDLL!=NULL)</p>
<p>{</p>
<p>return; </p>
<p>}</p>
<p>//</font><font SIZE="3">载入</font><font FACE="Times New Roman" SIZE="3">Mymaths.DLL</font><font SIZE="3">文件</font><font FACE="Times New Roman" SIZE="3">.</p>
<p>ghMathsDLL=LoadLibrary("mymaths.DLL");</p>
<p>//</font><font SIZE="3">如果载入</font><font FACE="Times New Roman" SIZE="3">DLL</font><font SIZE="3">失败,提示用户</font><font FACE="Times New Roman" SIZE="3"></p>
<p>if(ghMathsDLL==NULL)</p>
<p>{</p>
<p>AfxMessageBox("Cannot load DLL file!");</p>
<p>}</p>
<p>//</font><font SIZE="3">获得</font><font FACE="Times New Roman" SIZE="3">DLL</font><font SIZE="3">中</font><font FACE="Times New Roman" SIZE="3">Summary</font><font SIZE="3">函数的地址</font><font FACE="Times New Roman" SIZE="3"></p>
<p>Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");</p>
<p>//</font><font SIZE="3">获得</font><font FACE="Times New Roman" SIZE="3">DLL</font><font SIZE="3">中</font><font FACE="Times New Roman" SIZE="3">Factorial</font><font SIZE="3">函数的地址</font><font FACE="Times New Roman" SIZE="3"></p>
<p>Factorial=(FACTORIAL)GetProcAddress(ghMathsDLL,"Factorial");</p>
<p>}</p>
<p></font><font SIZE="3"> </font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">在</font><font FACE="Times New Roman" SIZE="3">testdlg.cpp</font><font SIZE="3">文件开头,加入:</font><font FACE="Times New Roman" SIZE="3"></p>
<p>//The instance of the Mymaths.DLL library</p>
<p>HINSTANCE ghMathsDLL=NULL;</p>
<p>//declare the Summary() function from the Mymaths.DLL libray.</p>
<p>typedef int (*SUMMARY)(int);</p>
<p>SUMMARY Summary;</p>
<p>//declare the Factorial() function from</p>
<p>//the Mymaths.DLL library.</p>
<p>typedef int (*FACTORIAL)(int);</p>
<p>FACTORIAL Factorial;</p>
<p></font><font SIZE="3">首先加入一个</font><font FACE="Times New Roman" SIZE="3">ghMathsDLL</font><font SIZE="3">的全局变量,它是动态连接库载入后的句柄(同应用程序一样,每个动态连接库载入都会有一个句柄和它相对应)。应用程序通过句柄访问库中的函数。然后加入</font><font FACE="Times New Roman" SIZE="3">Summary</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">Factorial</font><font SIZE="3">函数指针的类型定义。</font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">在</font><font FACE="Times New Roman" SIZE="3">LoadDLL()</font><font SIZE="3">函数定义中,检查动态连接库句柄是否为空;若为空,则用</font><font FACE="Times New Roman" SIZE="3">LoadLibrary</font><font SIZE="3">载入该动态连接库。然后用</font><font FACE="Times New Roman" SIZE="3">GetProcAddress</font><font SIZE="3">取得</font><font FACE="Times New Roman" SIZE="3">Summary</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">Factorial</font><font SIZE="3">函数地址。</font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">在</font><font FACE="Times New Roman" SIZE="3">OnFactorial</font><font SIZE="3">和</font><font FACE="Times New Roman" SIZE="3">OnSummary</font><font SIZE="3">函数开头,调用</font><font FACE="Times New Roman" SIZE="3">LoadDLL()</font><font SIZE="3">,载入动态连接库。现在编译运行程序,按</font><font FACE="Times New Roman" SIZE="3">Factorial</font><font SIZE="3">按钮测试一下程序。<b></p>
<p></b></font><font color="#3973DE" SIZE="3">应用程序是如何查找</font><font color="#3973DE"><font FACE="Times New Roman" SIZE="3">DLL</font><font SIZE="3">文件的</font></font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">应用程序</font><font FACE="Times New Roman" SIZE="3">test</font><font SIZE="3">按以下顺序查找动态连接库文件:<ul>
<li>当前目录下(因此要将动态连接库拷贝至<font FACE="Times New Roman" SIZE="3">DEBUG</font>目录下,因为可执行文件在该目录下)</li>
<li><font FACE="Times New Roman" SIZE="3">Windows</font>目录</li>
<li><font FACE="Times New Roman" SIZE="3">Windows</font>系统目录</li>
<li><font FACE="Times New Roman" SIZE="3">PATH</font>环境变量中设置的目录</li>
<li>列入映射网络的目录表中的目录</font></li>
</ul>
<p><font SIZE="3"><b> </p>
<p></b><font color="#3973DE">调用动态连接库中的函数的方法</font></font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">有两种方法可以调用动态连接库中的函数:</font><font FACE="Times New Roman" SIZE="3"></p>
<p>1.</font><font SIZE="3">通过引入库:</font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">利用</font><font FACE="Times New Roman" SIZE="3">Visual C++</font><font SIZE="3">提供的</font><font FACE="Times New Roman" SIZE="3">IMPLIB</font><font SIZE="3">工具为动态连接库生成引入库,为引入库设计一个头文件:</font><font FACE="Times New Roman" SIZE="3"></p>
<p>#ifndef _MYMATH_H</p>
<p>#define _MYMATH_H</p>
<p>extern </font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">C</font><font SIZE="3">”</font><font FACE="Times New Roman" SIZE="3"></p>
<p>{</p>
<p>int Summary(int n);</p>
<p>int Factorial(int n);</p>
<p>}</p>
<p>#endif</p>
<p></font><font SIZE="3">将该头文件包含在使用动态连接库的源文件中,连接应用程序时会连接上该引入库。这样,应用程序就可以象使用静态连接库一样自由的使用动态连接库中的函数了。注意要把动态连接库拷贝到应用程序可执行文件所在的目录(</font><font FACE="Times New Roman" SIZE="3">\TEST\DEBUG</font><font SIZE="3">)下。</font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">这是一种常用的方法。实际上,应用程序就是通过这种方式访问</font><font FACE="Times New Roman" SIZE="3">Windows</font><font SIZE="3">的</font><font FACE="Times New Roman" SIZE="3">API</font><font SIZE="3">函数的。</font><font FACE="Times New Roman" SIZE="3">Windows</font><font SIZE="3">为其内核动态连接库生成引入库并提供了头文件。应用程序在编译时将引入库的信息带入可执行文件中,在运行时通过引入库信息访问</font><font FACE="Times New Roman" SIZE="3">API</font><font SIZE="3">函数。</font><font FACE="Times New Roman" SIZE="3"></p>
<p>2. </font><font SIZE="3">直接指定库和函数地址</font><font FACE="Times New Roman" SIZE="3"></p>
<p></font><font SIZE="3">这种方式适合于一些提供文件格式转换等服务的动态连接库。比如,一个程序带有多个动态连接库,分别用于访问</font><font FACE="Times New Roman" SIZE="3">JPG</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">BMP</font><font SIZE="3">、</font><font FACE="Times New Roman" SIZE="3">GIF</font><font SIZE="3">等多种图像文件格式,这些动态连接库提供了相同的库函数接口。此时,无法使用引入库方式指定库函数。可以采用下面的方法来解决这个问题。</font><font FACE="Times New Roman" SIZE="3"></p>
<p>HANDLE hLibrary;</p>
<p>FARPROC lpFunc;</p>
<p>int nFormat;</p>
<p>if(nFormat==JPEG)//</font><font SIZE="3">如果是</font><font FACE="Times New Roman" SIZE="3">JPEG</font><font SIZE="3">格式,装入</font><font FACE="Times New Roman" SIZE="3">JPEG</font><font SIZE="3">动态连接库</font><font FACE="Times New Roman" SIZE="3"></p>
<p>{</p>
<p>hLibrary=LoadLibrary(</font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">JPEG.DLL</font><font SIZE="3">”</font><font FACE="Times New Roman" SIZE="3">);</p>
<p>}</p>
<p>else//</font><font SIZE="3">是</font><font FACE="Times New Roman" SIZE="3">GIF</font><font SIZE="3">格式</font><font FACE="Times New Roman" SIZE="3"></p>
<p>hLibrary= LoadLibrary(</font><font SIZE="3">“</font><font FACE="Times New Roman" SIZE="3">GIF.DLL</font><font SIZE="3">”</font><font FACE="Times New Roman" SIZE="3">);</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -