BPL 是一种特别的 DLL;

使用 Delphi 开发程序,可以把一个大程序的一部分,独立编译成一个 BPL,一个 Delphi 里面称作 Package 的东西,这里中文我们称作【包】,然后让 EXE 去加载它。

一个 EXE 加载 BPL 有两种模式:1. 静态加载;2. 动态加载;

关于静态加载:

EXE 静态加载一个 BPL,如果 EXE 在启动的时候系统里面没有正确的 BPL 文件,EXE 会启动失败。

关于动态加载:

动态加载有很多好处。比如,BPL 文件不存在的时候,EXE 不会启动不成功;比如,EXE 可以在运行期,动态加载 / 卸载 BPL 包。既然可以在运行期卸载后再重新加载,就可以在运行期动态替换不同的 BPL 包获得不同的功能。这也是一些插件的实现方式。

当然,插件的方式,采用 DLL 也是可以的。但 Delphi 调用 DLL,就没法使用 DLL 内部的 Delphi 对象,因为 DLL 是一个 WINDOWS 底下的通用标准,C / C++ 也是能够用到。采用 Delphi 自己的 BPL 则可以直接访问里面的 Delphi 类 / 对象。

动态加载 BPL 的几个注意要点:

动态加载 BPL 有两种方式:1. 通用方式;2. 基于 RTTI;

1. 通用方式,先看加载的代码:

procedure TForm1.Button2Click(Sender: TObject);
varS: string;
begincase RadioGroup1.ItemIndex of0: S := 'MyBPL1.bpl';1: S := 'MyBPL2.BPL';end;PackageModule := LoadPackage(S);AClass := GetClass('TFmBPLMain');   //这里使用 GetClass 无法找到类。但直接使用类是可以的。 // 无法找到类的原因是这个 EXE 没有勾选 RunTimePackagesif Assigned(AClass) thenbeginAForm := TComponentClass(AClass).Create(Application) as TForm;AForm.Show;end;
ene;

上述代码有两个需要注意的前提条件:

A. 这个加载 BPL 的 EXE 程序,必须在其 Options / Packages / Link with Rum Time Packages 的菜单里面,勾选;通常情况下,勾选后,Delphi IDE 会自动在下面的 Run Time Packages 里面,自动填入一大堆【包】的名字,基本上就是一个 Delphi 程序运行所需要的所有的包。这样编译出来的 EXE 特别小,但这个 EXE 在发布到其它电脑上的时候,需要记得把 Delphi 带来的这些包一起拷贝发布过去,否则 EXE 不能正常启动。

A.1. 如果上述 Run Time Packages 里面的包的名字,都删除掉,编译出来的 EXE 会比较大,也能正常运行,也能正常 LoadPackage 加载 BPL 文件成功,但是,AClass = GetClass('TFmBPLMain'); 这一句会返回 nil,找不到这个类。

B. GetClass 能够成功的第二个前提:BPL 里面的这个 TFmBPLMain 的代码里面,需要自动注册这个类,才可以根据类名称字符串找到类类型。注册的代码是:initialization RegisterClass(TFmBPLMain);

要点:BPL 里面的这个 TFmBPLMain 必须在它的 initialization 里面,注册这个类,EXE 里面的 GetClass 函数才可以通过类名称字符串找到这个类。否则返回 nil;

常见问题:如果代码都没问题,但 GetClass 返回 nil,检查 1. BPL 里面有没有注册类;2. EXE 的 RunTime Package 是否打勾,如果打勾,则检查填写的包名称是否有遗漏。

=======================

2. RTTI 方式,先看代码:

procedure TForm2.Button1Click(Sender: TObject);
varS: string;LContext: TRttiContext;LPackage: TRttiPackage;LClass: TRttiInstanceType;aForm: TForm;unitClass: string;H: HINST;RT: TRttiType;
beginS := 'MyBPL1.bpl';PackageModule := LoadPackage(S);if PackageModule = 0 then raise Exception.Create('加载 BPL 失败!');//==========================unitClass := 'UFmMainBPL.TFmBPLMain';//unitClass := 'TFmBPLMain';    //只写类名,LPackage.FindType 返回 nil;{------------------------------------------------------------------------------以下代码测试通过。在调试以下代码时碰到的问题:1. 在这个 EXE 的 Options /  RunTimePackage 里面,把系统自动加载的包的名字全部去掉,则 LContext.GetPackages 只有一个包,就是这个 EXE 自己;在 RunTimePackage 里面加上 rtl 包的名字以后,才能找到加载的 BPL;2. 找到加载的 BPL 以后,通过 'UFmMainBPL.TFmBPLMain' 名字找不到对应的 Class。把系统自动加载的全部包名称都放进 RunTimePackage 里面以后,能找到并创建 BPL 里面的 Form 成功。上述测试的前提是 BPL 里面的 Form 有:initialization  RegisterClass(TFmBPLMain); 注册自己。测试将 BPL 里面的注册 RegisterClass(TFmBPLMain) 代码去掉,以下程序仍然可用。------------------------------------------------------------------------------}AClass := GetClass('TFmBPLMain');LContext := TRttiContext.Create;trytryRT := LContext.FindType(unitClass);for LPackage in LContext.GetPackages() dobeginif SameText(ExtractFileName(LPackage.Name), S) thenbeginLClass := LPackage.FindType(unitClass) as TRttiInstanceType;aForm := LClass.MetaclassType.Create as TForm;aForm.Create(nil);aForm.WindowState := wsNormal;aForm.Position := poScreenCenter;aForm.Show;end;end;exceptShowMessage('单元名和类名是大小写敏感的');end;finallyLContext.Free;end;
end;

上述代码,通过 Delphi 的 RTTI 来获得加载的包里面的类;前提:

0. DELPHI XE 以上的版本。

1. BPL 里面的类,无需注册类,也即是无需有 initialization RegisterClass(TFmBPLMain);  这样的代码,通过 RTTI 也可以获得类。

2. EXE 必须勾选 Link with run time packages;

3. 勾选后,run time packages 里面填入的包名称要足够。如果缺少了必要的包名称,将会:

3.1. 缺少 RTL 则 LContext.GetPackages 里面没有加载成功的 BPL 包,只有 EXE 自己的名字;

3.2. 缺少其它的必要的包(暂时不清楚具体哪个包),则 LPackage.FindType 函数返回的 LClass 虽然不是 nil 但是类型不对,导致后面的创建 TForm 的代码会提示类型错误。

3.3. 把程序在勾选 Link with run time packages 时的默认全部包的名字都拷贝进去再重新编译运行,上述代码通过。

问题注意:因此,这里需要注意的问题仍然是检查这个 EXE 的 link with run time packages 的勾选以及里面填写的包的名字。

BPL 和动态加载包相关推荐

  1. bpl文件java,在LoadLibrary中动态加载BPL失败

    我想在Delphi 10 Seattle(Update 1)或Delphi 10.1 Berlin项目(Enterprise版本)中动态加载BPL模块 . 但LoadPackage函数失败并显示消息( ...

  2. Java运行时动态加载类之ClassLoader加载class及其依赖jar包

    需求场景是:通过ClassLoader动态加载外部class文件,class文件又依赖某个具体jar包,需要动态加载jar包,采用URLClassLoader. 1.xml配置文件 <?xml ...

  3. android jar 加入图片,Android动态加载外部jar包及jar包中图片等资源文件

    Android动态加载外部jar包及jar包中图片等资源文件 Android应用程序由Java开发,因此Java中许多实用的特性,在Android中也有体现.动态加载Class,也就是外部jar包,在 ...

  4. flink sql udf jar包_Java动态加载Jar实例解析

    导读:在实际项目开发中,有时会遇到需动态加载jar包的应用场景.如将Flink的UDF自定义方法制作成方法库(既打成一个Jar),在提交给Flink集群的Job中动态加载jar便可使用.下面将举一个简 ...

  5. java spring包_java 自定义加载器,加载spring包,动态加载实现,jar包隔离,tomcat加载webapp方式...

    java 自定义加载器,加载spring包,动态加载实现,jar包隔离,tomcat加载webapp方式 发布时间:2018-08-20 12:02, 浏览次数:774 , 标签: java spri ...

  6. Android插件化开发之动态加载本地皮肤包进行换肤

    Android插件化开发之动态加载本地皮肤包进行换肤 前言: 本文主要讲解如何用开源换肤框架 android-skin-loader-lib来实现加载本地皮肤包文件进行换肤,具体可自行参考框架原理进行 ...

  7. Android动态加载dex文件/jar包的纯原生代码实现(dex文件由服务端下发)

    介绍原理的文章有很多,我就不再多说,直奔主题: 一.生成dex文件(源码下载地址:https://download.csdn.net/download/wanggangyanqing/18658862 ...

  8. 爬虫Spider 05 - 代理参数-proxies | 控制台抓包 | requests.post() | 动态加载数据抓取-Ajax

    文章目录 Spider 04回顾 requests.get()参数 常见的反爬机制及处理方式 Spider 05笔记 代理参数-proxies **控制台抓包** **requests.post()参 ...

  9. 解决URL存在特殊符号、异步线程池配置、动态加载lib下所有jar包

    一.解决URL存在特殊符号|{}?&.URL中包含%2F.URL中包含%5C import lombok.extern.slf4j.Slf4j; import org.springframew ...

最新文章

  1. 图论 ---- CF700 C. Break Up(Tarjan找桥+枚举+思维)
  2. Abstract class虚拟类
  3. java中三种转string的方法_java中int,char,string三种类型的相互转换
  4. SQL 语句中 where 条件后 写上1=1 是什么意思
  5. HTML5笔记——formData
  6. ros下的python代码的编写与回调函数
  7. JMS(三):MessageListener
  8. python网络安全协议_python网络安全
  9. 4怎么打开项目_苹果电脑怎么把文件复制到u盘
  10. WinForm程序启动控制台窗口Console
  11. HCIE Security AC的准入技术 备考笔记(幕布)
  12. 唯一索引和普通索引的区别
  13. CSS RESET —— 浏览器样式重置
  14. red hat linux 7.1 使用手册!,linux入门教材(Red Hat Linux 7.1)
  15. Leaflet--建设移动设备友好的互动地图
  16. 【leetcode-652】寻找重复的子树
  17. 如何实用gho文件安装操作系统
  18. day05-回归测试和验收测试
  19. 书单|互联网企业面试案头书之运营篇
  20. 28 诊断偏差和方差:学习曲线 (28 Diagnosing bias and variance_ Learning curves)

热门文章

  1. Java支付宝二维码支付和退款,微信二维码支付
  2. 移动OA:企业微信和传统OA厂商APP如何选择?
  3. 有哪些博客支持google adsense广告?
  4. java全套视频教程资料
  5. Python初识对象
  6. 术语-BPM:BPM
  7. VirtualBox 不能为虚拟电脑 打开一个新任务 VERR_NEM_VM_CREATE_FAILED
  8. [2021-09-12]我所知道的最新CSGO国服能取回皮肤的国内开箱网站大全
  9. 面向中小企业的SpringBoot管理系统,拿来学习真香
  10. 2021-AFCTF