BPL vs. DLL

第一部分:有关包的介绍

一般我们编写编译一个DELPHI应用程序时,会产生一个EXE文件,也就是一个独立的WINDOWS应用程序。很重要的一点:区别于Visual Basic,DELPHI产生的是预先包裹的应用程序是不需要大量的运行库(DLL's)。

假设:打开Delphi默认的工程(只有一个空白form),F9她将编译生成一个大约295 KB (Delphi 5)的可执行文件。然后打开Project | Options,把‘Build with runtime packages’ 选上再编译一下,EXE文件大小就只有15 KB左右了。

我们编译一个DELPHI应用程序时默认地没有选择'Build with runtime packages',编译器将把程序运行所需要的代码直接写入你的EXE文件中,因此产生的程序是一个相对独立的程序,并不需要任何附属的支持文件(例如动态运行库文件DLL),这也就知道了为什么DELPHI产生的应用程序为什么都那么大。

要建立尽可能小的DELPHI程序,方法之一就要充分发挥Borland package libraries的作用,简称BPL。

先说什么是包?

简而言之,一个包就是一个在DELPHI的IDE环境中被DELPHI应用程序共享的特殊的动态链接库 。包允许我们通过多级应用将我们的程序的一部分当做一个分离的模块供其他应用程序来共享。

包大致可分为运行期包(Run-time packages)和设计期包(Design-time packages):

运行期包-当运行程序时提供VCL和库函数的支持,操作上很类似标准的动态链接库 。

设计期包-用来在DELPHI的IDE环境安装控件和为控件建立特殊的属性编辑器 。设计期包允许包含控件、属性和控件编辑器等等,在IDE环境中,这类包是程序设计所必需的,也仅仅是DELPHI使用,并不和开发的应用程序一起分发。

知道这些包的运用,我们也就知道了运行期包是如何做处理和它们对DELPHI程序员有什么帮助了。

有一点必须说明:想很好地运用包并不要求你先成为一个成熟的控件编写者。DELPHI编程初学者也可以和应该尝试去接触包的概念,这将有利于你更好地理解包和DELPHI的工作关系。

第二部分:适时运用包裹和DLL

一般都认为加入WINDOWS操作系统中的动态运行库是一种最有用最高效的应用。在WINDOWS系统中,很多应用程序同时运行可能会引起了内存方面的问题,很多程序执行相似的操作任务,但各自又由不同的代码来控制并完成任务,动态运行库的作用就是将你的执行程序中的这些代码放到一个系统共享环境下的DLL中去 。可能最为直观的动态链接库例子就是WINDOWS操作系统自己和它本身所带的API了。

动态链接库通常都是用来集合过程(procedure)和函数 (function)以供程序调用。当然我们在编写动态链接库的同时,也可以把一个DELPHI FORM放到一个DLL中去(例如一个AboutBox FORM),此外我们也可以在DLL中存储程序所需要的资源(resources)。更多关于DELPHI如何操作使用动态链接库,请参考相关书籍,不再赘述。

在比较DLLs 和BPLs之前,我们先要知道可执行文件的2种代码链接的方式:静态链接和动态链接 。

静态链接就是当一个DELPHI工程被编译的时候,工程所需要的所有代码将被直接 链接入你的程序执 行文件。结果就是执行文件将包含程序所需要使用到的所有单元(units),你也许会说这样代码有点冗长,因为在通常默认情况下,一个FORM单元的 uses子句列举了至少5个基本单元(如:Windows, Messages, SysUtils,...),尽管如此,DELPHI还是能够智能地自动链接单元中真正要用到的代码到工程代码中,从而尽可能地减少了执行文件的大小。使用静态链接 ,我们的应用程序就是一个相对独立的程序,不需要任何额外的支持文件或动态链接库(暂时不考虑BDE和ActiveX构件)。DELPHI中默认 使用的就是静态链接方式。

动态链接就是应用程序将和标准的动态链接库(DLLs)一起运行 。动态链接方式不需要将代码直接建立到每个应用程序中去,单独为多个应用程序提供多线程的库函数支持,任何程序运行期间才需用到的包才将被加载,更值得一提的是:程序在动态方式需要调用的包是自动加载的 ,因此你不需要专门写加载包的代码。

方法:简单地选中在Project | Options 对话框中'Build with runtime packages'复选框后,再次编译你的程序,你的程序代码将自动链接到动态运行包,而不是将引用单元都静态链接入你的工程执行文件。

是选择BPL 还是 DLL?区别又在哪里?

你可能很奇怪为什么要选择使用运行期包,而不是DLL,或者还有其他什么方法。

相对于DLL而言,包裹的概念是DELPHI开发中所特有 的,就是说其他语言编写的应用程序不能引用DELPHI建立的包裹。即使包是一种被DELPHI编写的应用程序所使用的动态链接库,它也同时提供给了DELPHI程序员更多的库函数支持。

通常我们在DELPHI中建立动态链接库(DLLs)是用来存储不同环境下 应用程序所需要使用到的过程和函数,而包不仅能够包含代码单元(untits)、构件和FORMs,还能包含DELPHI中的类(classes)-这就使我们能够在其中引用对象向导编码(object oriented code)。在包裹中,我们可以保存完整的通用DELPHI构件,而动态运行库(DLL's)对此则无能为力了。

此外,在缩减程序代码上,DLLs和BPLs扮演着同样重要的角色,其主要原因就是在使用包裹或动态链接库技术后,都直接地减少了程序的文件大小 。当然,还要说明的是:执行程序需要加载的DLLs或BPLs也可能会是很庞大的。例如如果需要分发你的包裹文件(主要是VCL包,vcl50.BPL)至少有2MB左右。

尽管如此,如果你是要分发共享同个包的多个应用程序,你就可以省很多事了。当用户方系统中已经存在程序运行需要的部分文件(如:标准的DELPHI BPLs)后,就只需要下载程序的最小执行文件了。如果你的程序工程主要是通过INTERNET等方式分发和开展,那效率显然有很大的提高。

同时,包的应用也节省系统内存 ,因为动态链接的结果就是:只有一个VCL被读入内存供所有使用运行期包的DLEPHI应用程序使用。

包裹的版本问题

当你想升级你的动态链接库时(改变其中一些执行函数),你可以简单地编译产生新的程序文件,并上载新版本文件,所有正在使用该动态链接库的应用程序仍将工作(除非你已经将存在的旧版本程序去除)。

换个角度来讲,在升级新包裹文件的同时,不要忘记升级程序的执行文件。正如你所了解的,包裹文件就是一个单元文件(units)的集合,所有编译过的单元文件(DCU)都含有版本信息 ,因此,除非我们有单元文件的源码(source),否则我们不能在DELPHI4或5中使用编译过的单元,所以一旦我们改变了单元文件中接口部分uses 子句中列举出的任一单元文件,该文件就需要重新编译。编译器将检查DCU文件的版本信息,并决定单元是否需要重新编译。因此我们不能在DELPHI5编译的应用程序中使用在DELPHI6下编译的包,任何为你的应用程序服务的包和你的应用程序必须在相同环境下编译。

因此,当给包裹命名的时要保留包裹名中包含有DELPHI的版本信息(如'AboutDP50',其中50就代表Delphi 5)。这可以有效防止文件版本的冲突问题,也可以避免很多不必要的麻烦,包使用者可以更清楚包的版本和包裹适用于哪个DELPHI编译器。

如果你要分发运行期或设计期包给其他DELPHI程序员,建议同时提供了.DCP(含有包的头信息和各个单元文件)和.BPL文件,还有包中所包含的所有单元文件的.DCU文件。

第三部分:建立和使用运行期包

建立一个包裹

建立一个包很简单,但在建包之前要做一些准备工作。首先,你需要知道你准备建立哪种类型的包文件:运行期包还是设计期包,或两者都是;其次是,建立、调试,反复地测试你想放置到包中去的单元文件;最后,为建立的包裹文件命名,还有就是选择一个合适的地方来存放文件。

建立一个新的运行期包,按照以下步骤:

1.启动DELPHI,并选择File | Close All关闭默认的工程。

2.选择File | New...,在"New items"对话框中的"new"页面中双击Package图标(如图),就会出现包裹编辑器(如图):包裹编辑器包含2个文件夹:Contains和Requires。

3.点击Add按钮,可以增加一个单元文件(构件或是一个简单的代码单元文件)。注意:你添加的是PAS源码文件而不是编译后的DCU文件。当你添加单元文件的同时,包中的单元的名字就显示在包裹编辑器的Contains文件夹中了。如图中添加了FindFile和PictureClip的单元文件。

4.打开Requires文件夹,展开的列表表示包裹所需要的包的DCP文件,包裹文件最基本的就需要引用含有绝大部分标准可视控件的vcl50.dcp文件。

5.当你添加完单元文件,单击Options按钮,在Description面板中的Usage options组中你需要选择包裹种类:是设计期包,还是运行期包,或者两者都是。如果选择Runtime only(仅运行期包),其他包的使用者将无法将图示2个构件安装到IDE环境中去。

6.使用File | Save保存包工程文件(DPK),然后保存包文件,如AboutDP50,包裹文件的命名将很重要。

7.在包裹器中,单击Compile按钮来编译包。

8.如果不出什么意外,编译包后将建立一个包裹文件(BPL文件),期间你可能还要确定你必须增加的其他包裹(例如VCLX50),这些包都将在Requires文件 夹中列出。

9.完成,Borland package library文件已经成功建立,就等着使用了。

在包裹编辑器中有一个Install按钮,就是用来将当前包裹安装成一个设计期包的 。如果包裹是run-time only(仅运行期包),那Install按钮将无法使用。

关于所建立的这些文件

除了DPK文件和那些单元源码文件,DELPHI还使用包裹的动态链接版本产生一个BPL文件和一个含有包内标识信息DCP文件,DCP文件就是包中所包含单元文件的编译文件(DCU)的标识信息的集合 。

使用运行期包设计程序

开始使用动态链接编写应用程序时,不需要写代码去加载运行期包裹,只需要在Project | Options中做相关设置,选择在Packages页的Runtime Packages编辑框中的包裹列表,编译程序时将自动链接。应用程序要使用到一个运行期包时,使用ADD按钮来增加包裹文件。

注意:尽管一个应用程序被链接到运行期包,程序的USES子句所列出的单元文件也必须都是存在的,编译运行期包裹只是告诉应用程序哪里可以找到构件代码而已。

当配置一个使用到运行期包裹的应用程序时,确定用户拥有可执行文件和程序所需的库文件(.BPL或.DLL)。如果库文件在和EXE文件不同的目录下,必须将其指定到系统所能到达的目录。因此,最好的选择就是Windows/System系统目录。

总而言之

包裹使你能够有弹性地选择应用程序的分发方式,也使构件的安装变简单了 ,此外,使用包裹也减少了应用程序的文件大小 ,因此,使用包裹的开发方式还是具有不小的意义的。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/aroc_lo/archive/2010/11/15/6009224.aspx

时间: 2024-11-03 12:18:44

BPL vs. DLL的相关文章

Delphi中的包(三):bpl和dll

曾经听说过"bpl就是一种特殊的dll",但是没有想到这句话具 有这么大的意义.最近看到有人在属于某个dpk的Unit里面写export语句,觉得 非常惊奇.但是遍查delphi的help,与export相关的都是library.今天看了 <delphi源代码分析>,才知道上面这句话的含义.因此有下面的推论: 对dll工程来说,exports既可以写在工程文件里面,也可以写在Unit里面, 没什么区别. bpl是一种dll. 上面的exports很正常. 其实按<de

BCB/Delphi相关文件扩展名介绍

整理了一下用Delphi作的程序的源代码中常见的文件扩展名,并给出了这些文件扩展名的意义,以便源代码管理时作为参照,扩展名以字母为序(不需要进源代码库不表示不需要进库). ~* Delphi生成的备份文件,在版本控制库及发布代码中不应该出现这些文件,如果修改了某个文件却因某些原因没有保存的话,可以尝试使用这些文件恢复. bmp/wmf/emf/gif/jpg/pcx/png/tiff/ico/cur/ani 图形/图标/光标文件,这些文件如果使用到了也需要进源代码库. bpg 工程组文件(Bor

Delphi从Dll中导出类

从Dll中导出类 ,想必大家首先想到的是使用 bpl 包.这种方式有一个不好 ,那就是使用者必须清楚这个包中含有那些类 ,也就是说必须知道类的名字 -- 这在一定意义上是个限制 ,试想一种情况 ,使用者定义了一个底层的抽象类 (abstract class),然后在此基础上定义了许多应用类 (concrete class),那么 ,对于使用者来说 ,他希望在不知道具体有哪些类的情况下能使用这些类 -- 这 么说似乎有些玄 ,但实际情况确实如此 ,因为定义抽象类的时候并不能预料到以 后会有多少个具

包合并-delphi 插件(主程+dll) 怎么确定要带哪些包编译?如何将这些包进行合并?

问题描述 delphi 插件(主程+dll) 怎么确定要带哪些包编译?如何将这些包进行合并? delphi 插件(主程+dll) 带包编译 使用了第三方控件后怎么确定要带哪些包编译?有没有什么方法查看?如何将这些包进行合并? 我的意思是将所有用到包都进行带包编译,因为使用的插件环境如果有重复包注册就会报错. 为了发布的简化,最后需要将这些包合并到一起? 各位做DELPHI插件时,对于这些包是怎么处理的? 解决方案 Delphi内有一个函数GetPackageInfo,可以获得包内部的所有信息,包

Win7系统提示“无法定位动态链接库user32.dll”的解决方法

user32.dll是Windows用户界面相关应用程序接口,用于Windows处理,基本用户界面等特性,比如创建窗口和发送消息等,有用户反馈在win7系统上运行某软件的过程中,出现提示无法定位程序输入点dwmhintdxupdate于动态链接库user32.dll上,导致这个软件无法使用,下载重装也没用,不知该如何解决了?针对此问题,下面小编整理了解决方法,给大家介绍Win7纯净版64位系统运行软件提示无法定位动态链接库user32.dll的解决方法. 操作方法: 1.首先重新启动或注销win

vs2008-VS搭配QT,x64平台下为挖三维编的dll,怎么调试

问题描述 VS搭配QT,x64平台下为挖三维编的dll,怎么调试 VS搭配QT,x64平台下为挖三维编的dll,怎么调试?新手,试过用挖三维打开调试,但是没看到界面在哪里,请懂得QT的前辈回答,谢谢! 解决方案 https://github.com/Vaa3D/Vaa3D_Wiki/wiki/Build-Vaa3D-on-Linux

封装dll-C# 中如何将一个类文件 封装成.dll文件

问题描述 C# 中如何将一个类文件 封装成.dll文件 我现在在c#程序里面写了几个通用的类,里面包括数据库的操作,网页表单的基本验证以及自己平时总结的一些很好用的方法,我现在想把这些类或者某一个类封装成一个dll文件,最好是所有的类都封装成一个dll,想请问一下各位怎么做,以前没做过将类封装成dll,麻烦大家帮帮小弟,最好有代码,谢谢了! 解决方案 封装成dll不就是将它编译成dll吗? 在bin文件下就有编译的dll 解决方案二: 在VS中新建一个类库工程,把你的类文件导到新建的工程里,编译

VC++动态链接库(DLL)编程之库的调试与查看

  在具体进入各类DLL的详细阐述之前,有必要对库文件的调试与查看方法进行一下介绍,因为从下一节开始我们将面对大量的例子工程. 由于库文件不能单独执行,因而在按下F5(开始debug模式执行)或CTRL+F5(运行)执行时,其弹出如图3所示的对话框,要求用户输入可执行文件的路径来启动库函数的执行.这个时候我们输入要调用该库的EXE文件的路径就可以对库进行调试了,其调试技巧与一般应用工程的调试一样. 通常有比上述做法更好的调试途径,那就是将库工程和应用工程(调用库的工程)放置在同一VC工作区,只对

dll-在 v2010中引用某个Dll后 所有.net程序无法运行

问题描述 在 v2010中引用某个Dll后 所有.net程序无法运行 重装的系统及vs2010. 一切正常. 在引用某个从网上下载的mysql.data.dll后,所有的.net程序都无法运行,就像没有安装framework一样. 但用IIS加载.net网页没问题. 运行不了后尝试重装过vs2010,所有framework运行库,重注册dll,都没用. 请问不重装系统怎么破? 解决方案 估计引用dll和你的系统崩溃之间只是巧合.你的系统被流氓软件破坏了. 不重装系统要想解决除非你有足够多的钱和时