科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道应用软件Delphi中的包(二):关于bpl

Delphi中的包(二):关于bpl

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文讲解Delphi中的包,关于bpl的部分

作者:soobey 来源:blog.csdn.net/soobey  2007年9月15日

关键字: 软件

  • 评论
  • 分享微博
  • 分享邮件

现在我们看到,package工程的入口dpr文件结构中没有uses子句,但是取而代之的是contains子句。从字面上说,这好像是指明这个包将会由哪些Unit组成。这些Unit再去use别的unit,这样就又形成了一张有向图。是这样的吗?我们将Package1的contain部分改成

contains

UnitForm1 in 'UnitForm1.pas' {Form1};

这样仅包含UnitForm1。而UnitForm1中因为存在继承关系,必然要use UnitFormAnother。于是自然package1中必须包含三个Unit:Package1.dpk、UnitFormAnother.pas、UnitForm1.pas。然后编译,结果报警说:隐式地引入了UnitFormAnother。先不管这个警告,然后改exe工程:把FormMain的button1Click改成

procedure TFormMain.Button1Click(Sender: TObject);

var

LForm:TForm1;

begin

LForm:=TForm1.Create(Application);

LForm.ShowModal;

LForm.Free;

end;

当然,还要在FormMain的Uses里面加上UnitForm1,然后修改runtime package列表,加上package1。然后编译,调试,检查Module情况。结果发现ProjectExe里面包含FormMain,而Package1.pbl里面包含我们所推测的三个Unit。另一个试验是,如果在编译exe的时候,去掉列表中的package1,并且恰好能让编译器找到FormAnother和Form1(源文件也好,dcu也好),也可以成功编译。但是此时三个Form都跑到exe中间去了。

类似地,验证package2,发现:package2也可以编译过,前提是它能够找到FormAnother,此时package2中包含两个Form;如果把package2的require部分改成只依赖package1,那么最终编译出来的package2中则只含Form2。如果两个package都包含FormAnother,而exe同时使用两个package的话,那么会产生编译错误。(是啊,两个package同时加载一个类,当我要使用的时候,到底是谁提供服务呢?)这种情况很容易发生,因为一方面FormAnother是Form1和Form2的公共基类;另一方面,在Contain子句里面很容易不小心漏掉FormAnother。所以编译器的提示还是很不错的,写程序还是按规矩办事,把contain写完整比较好。

因此,现在基本可以得到结论:

  1. 由dpr文件的runtime library(或者dpk文件的requires子句)出发,再继续搜索这些bpl require的bpl,直到获得所需的所有bpl文件。设这些bpl中包含的Unit组成集合A。然后从dpr文件的uses子句(或dpk文件的contains子句)出发,生成工程所需Unit的集合B。则最后编译目标仅包含B-A。其情况如下图

  2. 集合B中的Unit,如果存在于集合A中,则在连接时不需要对应的dcu文件,有bpl和bpc就好了。而B-A部分,要么必须有pas文件,要么需要有dcu文件。

现在,编译和连接的问题基本解决了,现在来研究加载。加载有两种,一种是自动的,由delphi控制;一种是手动的,在程序中写LoadPackage。先来搞清楚什么情况下会自动加载library。

测试是这样的,ProjectExe use UnitForm1, Package2 contains UnitForm2 requires package1,package1 contains UnitForm1和UnitFormAnother。在ProjectExe的Package list里面仅有package2。运行结果是:加载的包有rtl、vcl和package1,package2并没有出现。也就是说,自动装入内存的包是那些存在于A集合中,且跟B集合有交集的包。所有想要完全手工加载包,还必须要注意一些问题,起码它不能直接和间接地被require,包中的Unit也不能在Use里面出现。换句话说,调用者完全不知道被调用包的情况下才能避免自动装载。

既然调用者完全不知道被调用的包的信息,凭什么去调用呢?Delphi里面似乎没有头文件之类的东西。怎么获取这个包的接口呢?

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章