友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!阅读过程发现任何错误请告诉我们,谢谢!! 报告错误
一世书城 返回本书目录 我的书架 我的书签 TXT全本下载 进入书吧 加入书签

VC语言6.0程序设计从入门到精通-第73章

按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!




地址空间中。可以用两种方法进行这项操作 。第一种方法是让应用程序的源代码只引用 DLL 

中包含的符号。这样,当应用程序启动运行时,加载程序就能够隐含加载(或链接)需要的 

DLL 。第二种方法是在运行时让应用程序显式加载需要的 DLL 并且显式链接到需要的输出符 

号。换句话说,当应用程序运行时,其中的线程决定它是否要调用 DLL 中的函数。该线程可 

以将 DLL 显式加载到进程的地址空间,获得 DLL  中包含的函数的虚拟内存地址,然后使用 

该内存地址调用该函数。该方法的一切操作都是在应用程序运行时进行的。  

    当线程加载动态链接库的时候,是按照下面的搜索顺序查找并加载动态链接库文件的。  

    o  当前目录下(首先将动态链接库拷贝至 DEBUG  目录下,因为可执行文件在该目录下)。  

    o  Windows  目录。  

    o  Windows 系统目录。  

    o  PATH 环境变量中设置的目录。  

    o  列入映射网络的目录表中的目录。  

    下面将介绍隐式链接和显式链接这两种调用 DLL 的方式。  



10。3。1    隐式链接  



    如果程序员采用隐式链接方式建立一个 DLL 文件,链接程序会自动生成一个与之对应的 

LIB 导入文件。该文件包含了每一个 DLL 导出函数的符号名和可选的标识号,但是并不含有 

            LIB 文件作为 DLL 的替代文件被编译到应用程序项目中。当程序员通过静态链 

实际的代码。 

接方式编译生成应用程序时,应用程序中的调用函数与 LIB 文件中导出符号相匹配,这些符 

号或标识号进入生成的 EXE 文件中。LIB 文件中也包含了对应的 DLL 文件名(但不是完全 

的路径名),链接程序将其存储在 EXE 文件内部。当应用程序运行过程中需要加载 DLL 文件 

时,Windows 根据这些信息发现并加载 DLL ,然后通过符号名或标识号实现对 DLL  函数的 

动态链接。  

    下面的例子通过隐式链接调用 MyDll。dll 库中的 Min 函数。首先生成一个 TestDll 项目, 

在 DllTest。h 、DllTest。cpp 文件中分别输入如下代码:  



    //Dlltest。h  



    #pragma ment(lib ,〃MyDll。lib〃)  



    extern 〃C〃_declspec(dllimport) int Max(int a;int b);  



    extern 〃C〃_declspec(dllimport) int Min(int a;int b);  



    //TestDll。cpp  



    #include〃Dlltest。h〃  



    void main()  



    {  



        int a;  



        a=min(8;10);  



                                                                             ·257 ·  


…………………………………………………………Page 269……………………………………………………………

Visual C++ 6。0 程序设计从入门到精通  



         printf(〃 比较的结果为%dn〃,a);  



     }  



       在创建 DllTest。exe 文件之前,要先将 MyDll。dll 和 MyDll。lib 拷贝到当前工程所在的目 

录下,也可以拷贝到 windows 的 System 目录下。如果DLL 使用的是 DEF 文件,要删除 TestDll。h 

文件中关键字 extern 〃C〃 。TestDll。h 文件中的关键字 Progam mit 是要 Visual C++ 的编译器 

在  link 时,链接到  MyDll。lib       文件。当然,开发人员也可以不使用#pragma  ment(lib , 

〃MyDll。lib〃)语句,而直接在工程的 Setting→Link 页的 Object/Moduls 栏填入 MyDll。lib 即可。  



10。3。2    显式链接  



     显式链接方式对于集成化的开发语言(例如 Visual Basic )比较适合。有了显式链接,程 

序员就不必再使用导入文件,而是直接调用 Win32  的 LoadLibary 函数,并指定 DLL  的路径 

作为参数。LoadLibary 返回 HINSTANCE 参数,应用程序在调用 GetProcAddress 函数时使用 

这一参数。GetProcAddress 函数将符号名或标识号转换为 DLL  内部的地址。假设有一个导出 

如下函数的 DLL 文件:  



     extern 〃C〃 __declspec(dllexport) double SquareRoot(double d);  



     在隐式链接方式中,所有被应用程序调用的 DLL 文件都会在应用程序 EXE 文件加载时 

被加载在到内存中 。但如果采用显式链接方式,程序员可以决定 DLL 文件何时加载或不加载。 

显式链接在运行时决定加载哪个 DLL 文件。例如,可以将一个带有字符串资源的 DLL 模块 

以英语加载,而另一个以西班牙语加载。应用程序在用户选择了合适的语种后再加载与之对 

应的 DLL 文件。  

     在显式链接方式中,应用程序在执行过程中随时可以加载  DLL                                 文件,也可以随时卸载 

DLL 文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性,更适合解释性语 

言。不过实现显式链接比较复杂,除了要调用特定的Win32 的LoadLibrary 函数动态链接DLL , 

在应用程序退出之前,还应该用 FreeLibrary 或 MFC 提供的 AfxFreeLibrary 释放动态链接库。 

下面是通过显式链接调用 DLL 中的 Max 函数的例子,代码如下:  



     #include …  



     void main(void)  



     {  



         typedef int(*pMax)(int a;int b);  



         typedef int(*pMin)(int a;int b);  



         HINSTANCE    hDLL;  



         PMax Max;  



         HDLL=LoadLibrary(〃MyDll。dll〃);//加载动态链接库 MyDll。dll 文件;  



         Max=(pMax)GetProcAddress(hDLL;〃Max〃);  



         A=Max(5;8);  



         printf(〃 比较的结果为%dn〃,a);  



         FreeLibrary(hDLL);//卸载 MyDll。dll 文件;  



     }  



     在上面的程序片断中使用类型定义关键字 typedef ,定义指向和 DLL  中相同的函数原型 



 ·258 ·  


…………………………………………………………Page 270……………………………………………………………

                                                                                   第 10 章    动态链接库  



指针,然后通过 LoadLibray()将 DLL 加载到当前的应用程序中并返回到当前 DLL  文件的句 

柄,然后通过 GetProcAddress()函数获取导入到应用程序中的函数指针。函数调用完毕后,使 

用 FreeLibrary()卸载 DLL 文件。在编译程序之前,首先要将 DLL 文件拷贝到工程所在的目 

录或 Windows 系统目录下。  

     使用显式链接应用程序编译时不需要使用相应的 LIB 文件。另外,使用 GetProcAddress() 

函数时,可以利用  MAKEINTRESOURCE() 函数直接使用  DLL                                  中函数出现的顺序号,如将 

GetProcAddress(hDLL;〃Min〃) 改 为          GetProcAddress(hDLL;MAKEINTRESOURCE(2))                 ( 函 数 

Min()在 DLL 中的顺序号是 2 ),这样调用 DLL 中函数的速度将会很快,但是要记住函数的使 

用序号,否则会发生错误。  



10。4    开发 DLL  



     在   Visual  C++6。0    开发环境下,打开“FileNewProject ”选项,可以通过选择  Win32  

Dynamic…Link Library 或 MFC AppWizard'dll' 的不同方式来创建 Non…MFC Dll 、Regular Dll 、 

Extension Dll 等不同种类的动态链接库。  



10。4。1    创建 Non…MFC DLL 动态链接库  



     每一个 DLL 必须有一个入口点,这就像用 C 编写的应用程序一样,必须有一个 WinMain 

函数一样。在 Non…MFC  DLL  中 DllMain()是一个默认的入口函数,不需要编写自己的 DLL 

入口函数,用 DllMain()函数就能使动态链接库在被调用时得到正确的初始化。如果应用程序 

的 DLL 需要分配额外的内存或资源时,或者说需要对每个进程或线程初始化和清除操作时, 

需要在相应的 DLL 工程的 CPP 文件中对 DllMain() 函数按照下面的格式编写。  



     BOOL APIENTRY DllMain(HANDLE hModule;DWORD ul_reason_for_call;LPVOID lpReserved)  



     {  



          switch( ul_reason_for_call )  



          {  



          case DLL_PROCESS_ATTACH:  



                。。。。。。。  



          case DLL_THREAD_ATTACH:  



                。。。。。。。  



          case DLL_THREAD_DETACH:  



                。。。。。。。  



          case DLL_PROCESS_DETACH:  



                。。。。。。。  



          }  



          return TRUE;  



     }  



     关于 DllMain() 函数,在  10。2。1 节中已经作了详细介绍,这里不再赘述。DLL  是包含若 



                                                                                                 ·259 ·  


…………………………………………………………Page 271……………………………………………………………

Visual C++ 6。0 程序设计从入门到精通  



干个函数的库文件,应用程序使用 DLL 中的函数之前,应该先导出这些函数,以便供给应用 

程 序 使 用 。 要 导 出 这 些 函 数 有 两 种 方 法 , 一 是 在 定 义 函 数 时 使 用 导 出 关 键 字 

_declspec(dllexport) ,另外一种方法是在创建 DLL 文件时使用模块定义 DEF 文件。需要读者 

注意的是在使用第一种方法的时候,不能使用 DEF 文件。下面通过两个例子来说明使用这两 

种方法创建 DLL 文件的方法。  



      1.使用关键字_declspec(dllexport)  



      使用导出函数关键字_declspec(dllexport)创建 MyDll。dll,该动态链接库中有两个函数,分别 

用来实现得到两个数的最大和最小值。在 MyDll。h 和 MyDLL。cpp 文件中分别输入如下原代码:  



      //MyDLL。h  



      extern 〃C〃 _declspec(dllexport) int Max(int a; int b);  



      extern 〃C〃 _declspec(dllexport) int Min(int a; int b);  



      //MyDll。cpp  



      #include  



      #include〃MyDll。h〃  



      int Max(int a; int b)  



      {  



           if(a》=b)  



                 return a;  



           else  



                
返回目录 上一页 下一页 回到顶部 0 1
未阅读完?加入书签已便下次继续阅读!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!