10.2 DLLs的编写和调用
10.2.1 DLLs的编写 在Delphi环境中,编写一个DLLs同编写一个一般的应用程序并没有太大的区别。事实上作为DLLs 主体的DLL函数的编写,除了在内存、资源的管理上有所不同外,并不需要其它特别的手段。真正的区别在工程文件上。在绝大多数情况下,用户几乎意识不到工程文件的存在,因为它一般不显示在屏幕上。如果想查看工程文件,则可以打开View菜单选择Project Source项,此时工程文件的代码就会出现在屏幕的Code Editor(代码编辑器)中。一般工程文件的格式为: program 工程标题;uses 子句;程序体 而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,其它内容将在后边的两节中讨论。 10.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.编译程序,生成动态链接库文件。 10.2.1.2 动态链接库中的标准指示 在动态链接库的输出部分,用到了三个标准指示:name、Index、resident。1.namename后面接一个字符串常量,作为该过程或函数的输出名。如: exportsInStr name MyInstr;其它应用程序将用新名字(MyInstr)调用该过程或函数。如果仍利用原来的名字(InStr),则在程序执行到引用点时会引发一个系统错误。2.IndexIndex指示为过程或函数分配一个顺序号。如果不使用Index指示,则由编译器按顺序进行分配。Index后所接数字的范围为1...32767。使用Index可以加速调用过程。3.resident使用resident,则当DLLs装入时特定的输出信息始终保持在内存中。这样当其它应用程序调用该过程时,可以比利用名字扫描DLL入口降低时间开销。对于那些其它应用程序常常要调用的过程或函数,使用resident指示是合适的。例如: exportsInStr name MyInStr resident;