Windows的动态链接库原理及使用1
子句;
程序体 而DLLs工程文件的格式为: library 工程标题; uses 子句; exprots 子句; 程序体 它们主要的区别有两点: 1.一般工程文件的头标用program关键字,而DLLs工程文件头标用library 关键字。不同的关键字通知编译器生成不同的可执行文件。用program关键字生成的是.exe文件,而用library关键字生成的是.dll文件; 2.假如DLLs要输出供其它应用程序使用的函数或过程,则必须将这些函数或过程列在exports子句中。而这些函数或过程本身必须用export编译指令进行编译。 根据DLLs完成的功能,我们把DLLs分为如下的三类: 1.完成一般功能的DLLs; 2.用于数据交换的DLLs; 3.用于窗体重用的DLLs。 这一节我们只讨论完成一般功能的DLLs,其它内容将在后边的两节中讨论。 2.1.1 编写一般DLLs的步骤 编写一般DLLs的步骤如下: 1.利用Delphi的应用程序模板,建立一个DLLs程序框架。 对于Delphi 1.0的用户,由于没有DLLs模板,因此: (1).建立一个一般的应用程序,并打开工程文件; (2).移去窗体和相应的代码单元; (3).在工程文件中,把program改成library,移去Uses子句中的Forms,并添加适当的库单元(一般SysUtils、Classes是需要的),删去begin...end之间的所有代码。 2.以适当的文件名保持文件,此时library后跟的库名自动修改; 3.输入过程、函数代码。如果过程、函数准备供其它应用程序调用,则在过程、函数头后加上export 编译指示; 4.建立exports子句,包含供其它应用程序调用的函数和过程名。可以利用标准指示 name 、Index、resident以方便和加速过程/函数的调用; 5.输入库初始化代码。这一步是可选的; 6.编译程序,生成动态链接库文件。 2.1.2 动态链接库中的标准指示 在动态链接库的输出部分,用到了三个标准指示:name、Index、resident。 1.name name后面接一个字符串常量,作为该过程或函数的输出名。如: exports InStr name MyInstr; 其它应用程序将用新名字(MyInstr)调用该过程或函数。如果仍利用原来的名字(InStr),则在程序执行到引用点时会引发一个系统错误。 2.Index Index指示为过程或函数分配一个顺序号。如果不使用Index指示,则由编译器按顺序进行分配。 Index后所接数字的范围为1...32767。使用Index可以加速调用过程。 3.resident 使用resident,则当DLLs装入时特定的输出信息始终保持在内存中。这样当其它应用程序调用该过程时,可以比利用名字扫描DLL入口降低时间开销。 对于那些其它应用程序常常要调用的过程或函数,使用resident指示是合适的。例如: exports InStr name MyInStr resident; 2.1.3 DLLs中的变量和段 一个DLLs拥有自己的数据段(DS),因而它声明的任何变量都为自己所私有。调用它的模块不能直接使用它定义的变量。要使用必须通过过程或函数界面才能完成。而对DLLs来说,它永远都没有机会使用调用它的模块中声明的变量。 一个DLLs没有自己的堆栈段(SS),它使用调用它的应用程序的堆栈。因此在DLL中的过程、函数绝对不要假定DS = SS。一些语言在小模式编译下有这种假设,但使用Delphi可以避免这种情况。Delphi绝不会产生假定DS = SS的代码,Delphi的任何运行时间库过程/函数也都不作这种假定。需注意的是如果读者想嵌入汇编语言代码,绝不要使SS和DS登录同一个值。 2.1.4 DLLs中的运行时间错和处理 由于DLLs无法控制应用程序的运行,导致很难进行异常处理,因此编写DLLs时要十分小心,以确保被调用时能正常执行 。当DLLs中发生一个运行时间错时,相应DLLs并不一定从内存中移去(因为此时其它应用程序可能正在用它),而调用DLLs的程序异常中止。这样造成的问题是当DLLs已被修改,重新进行调用时,内存中保留的仍然可能是以前的版本,修改后的程序并 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |