Bpl就是Dll,这句话当然没错。
  简单的例子,当然可以做,而且可以做得很好,我就曾把左兄的离线浏览器改成了这样一
个版本: 实现多个数据连接方式,ADO、DOA、ODAC、IBX、KAO,每个连接对应它的特定数据
库,都以一个独立的BPL来实现;主程序没有任何连接数据库的代码,主窗体切换版本时只要
这样一段代码就行了:
class function TfrmMain.SelectVersion(AReadSettings: Boolean): Boolean;
var
  DMPkg, DMClassName: string;
  I: Integer;
  UserCanceled: Boolean;
begin
  Result := False;
  repeat
    DMPkg := 'DoaDmDLL.bpl';
    //简单版本,直接提示用户输入bpl的名称
    UserCanceled := not InputQuery(Application.Title, 'ModuleName:', DMPkg);

DMClassName := GetPackageDescription(PChar(DMPkg));
    I := Pos('[RICHEXPRDM]', DMClassName);
    try
      DM := nil;
    except
    end;
    //是正确的BPL,则开始载入
    if I > 0 then
    begin
      //取得Datamodule的类名
      DMClassName := Trim(Copy(DMClassName, I + 12, MAX_PATH));
      //卸载当前的BPL
      UnloadCurPkg;
      //用LoadPackage载入刚刚选择的BPL
      FHandle := LoadPackage(DMPkg);
      //创建Datamodule的实例
      DM := TDMClass(FindClass(DMClassName)).Create(Application);
      Result := True;
    end
    else
      Application.MessageBox('非法的DLL', '', MB_OK or MB_ICONERROR);
  until Result or UserCanceled;
end;
然后在DoaDM.pas里加这两句:
initialization
  RegisterClass(TDoaDM);

finalization
  UnregisterClass(TDoaDM);
编译成一个BPL就OK了。
这样用BPL做起来真的是非常简便,只要用LoadPackage以后,各单元就跟你直接uses差不多
了,initialization及finalization也会帮你执行,然后你就当做不存在BPL这回事一样用
就OK了。 这是BPL的好处,可以很方便的划分现有的代码成相对独立的模块。

但是,它也有几个致命的缺点,首先它无法象DLL一样,把它引用到的某一个或某几个BPL里的内
容编译进去,也就是说,只要你这个BPL引用了另一个BPL,发布的时候就必须两个BPL一起发
布,另外,只要一个BPL引用了某一个单元,其他的BPL就不能直接引用那个单元编译,而必须
引用一个公用的包含此单元的BPL,否则你这两个BPL是无法同时Load的。有了这两点,对于
大型项目来说,做起来是非常复杂的,各个模块之间的关系很难处理好,不象DLL,编译出
来后,各成各的体系,不会说因为这个DLL引用了这个单元,另一个DLL必须通过其他引用了
此单元的DLL来引用那个单元。

Delphi中Package是一件非常强大的工具,用的好可以起到非常清晰的
划分程序结构的作用。因为他内建描述信息,可以和当前代码无缝集成起来,
可以保护包括类在内的任何元素,相当于VC中的MFC Extension DLL的作用。
但是一直以来的文章都只介绍静态连接的方法,这其实限制了Package的使用
因为静态连接的Package失去了其灵活性,可配置性等等。至于通过函数入口
方式访问,实在是大材小用,那不如直接用DLL还方便一些。
   如何动态载入Package,使用其中的类、函数、变量等等?起始说穿了很
简单,就是做一个代理包。因为在一个Delphi程序中,每个unit只能存在
一份,否则发生冲突。要动态载入包,又得取得其中信息,又不能直接uses
包含信息的unit(否则引起冲突),解决办法是另外建一个代理包来作为桥梁
传递信息。下面是一个简单的例子,主程序使用到两个包,DemoPak包中有
一个简单的Form;RegPak是所谓的代理包,起到注册信息的作用。
主程序对RegPak静态使用(在Project Options里面设置了),对DemoPak
动态载入(通过LoadPackage),而DemoPak依赖于RegPak(requires),
并在初始化时向代理包RegPak注册自己的可用类,这里举例注册类信息,
你可以方便的改成注册其他信息

unit FormReg;

interface

uses
  Classes, SysUtils, Forms, Contnrs;

type
  TFormClass = class of TForm;

procedure RegisterFormClass(const AName: string; const AFormClass: TFormClass);
procedure UnregisterFormClass(const AName: string);
function FindFormClass(const AName: string): TFormClass;

implementation

var
  g_lstNames: TStringList;
  g_lstForms: TClassList;

procedure RegisterFormClass(const AName: string; const AFormClass: TFormClass);
begin
  g_lstNames.Add(AName);
  g_lstForms.Add(AFormClass);
end;

procedure UnregisterFormClass(const AName: string);
var
  Index: Integer;
begin
  Index := g_lstNames.IndexOf(AName);
  if Index <> -1 then
  begin
    g_lstNames.Delete(Index);
    g_lstForms.Delete(Index);
  end;
end;

function FindFormClass(const AName: string): TFormClass;
var
  I: Integer;
begin
  for I := 0 to g_lstNames.Count - 1 do
  begin
    if g_lstNames[I] = AName then
    begin
      Result := TFormClass(g_lstForms.Items[I]);
      Exit;
    end;
  end;
  Result := nil;
end;

initialization
  g_lstNames := TStringList.Create;
  g_lstForms := TClassList.Create;

finalization
  FreeAndNil(g_lstForms);
  FreeAndNil(g_lstNames);

end.

以上是RegPak的主要代码,因为举例,代码很简陋。主要思想就是保存注册信息,
提供查询方法。让我们看看在DemoPak中的使用

unit AboutForm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmAbout = class(TForm)
    lblAbout: TLabel;
  private
  public
  end;

var
  frmAbout: TfrmAbout;

implementation

uses FormReg;

{$R *.dfm}

initialization
  RegisterFormClass(TfrmAbout.ClassName, TfrmAbout);

finalization
  UnregisterFormClass(TfrmAbout.ClassName);
 
end.

在初始化时向RegPak的FormReg单元提交自己的类信息,因为每个Package在载入时
无论动态静态都会自动初始化,而RegPak被主程序静态引用,肯定已经初始化,所以直接
注册即可,非常简单。最后看看主程序中的使用

uses
  FormReg;

procedure TfrmMain.btnAboutClick(Sender: TObject);
var
  hModule: THandle;
begin
  hModule := LoadPackage('DemoPak.bpl');
  try
    with FindFormClass('TfrmAbout').Create(nil) do
    try
      ShowModal;
    finally
      Free;
    end;
  finally
    UnloadPackage(hModule);
  end;
end;

动态载入需要的包,查询需要的类的信息,使用之,最后卸载包。

象dll样输出 我已试成功了,而且是在mdi中试成功的。
贴出代码,大家同喜。希望bbkxjy来拿分。
主要的原因是bpl输出的目录默认为/bpl下。
而我一直没有在意。
bpl部分;
...
type
  TUIPackageForm = class(TForm)
    DataSource1: TDataSource;
    DBNavigator1: TDBNavigator;
    DBGrid1: TDBGrid;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

procedure ShowMDIChildForm(MainApp:TApplication);stdcall;
  exports
     ShowMDIChildForm;
var
  UIPackageForm: TUIPackageForm;
implementation
{$R *.DFM}
procedure ShowMDIChildForm(MainApp:TApplication);stdcall;
begin
  Application:=MainApp;
  UIPackageForm:=TUIPackageForm.Create(MainApp);
  UIPackageForm.Show;
end;
procedure TUIPackageForm.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  Action := cafree;
end;
动态调用的主程序部分。
type
  Tshowmdiform=procedure(MainApp:TApplication);stdcall;

showmdiform:Tshowmdiform;
begin
  UIConnect := LoadPackage('bpl');
  showmdiform:=getprocaddress(UIConnect,'ShowMDIChildForm');
  if (@showmdiform<>nil) then
      showmdiform(application)
    else showmessage('no prc');
end;

Bpl的使用以及与Dll的区别相关推荐

  1. Activex、OLE、COM、OCX、DLL之间区别、联系

    转自:http://baike.baidu.com/view/393671.htm 概述 .ocx是ocx控件的扩展名,与.exe .dll同属于PE文件.下面说说什么是ocx控件! OCX 是对象类 ...

  2. OCX和DLL的区别

    转自:http://blog.csdn.net/scucj/archive/2006/06/29/852181.aspx 一.关于DLL的介绍        DLL,动态链接库,Dynamic Lin ...

  3. C/C++ 知识点---LIB和DLL的区别与使用(网摘)

    LIB和DLL的区别与使用 原文出处:[远风工作室] 共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dyn ...

  4. LIB和DLL的区别与使用,非常详细

    2019独角兽企业重金招聘Python工程师标准>>> 共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供, ...

  5. [转]LIB和DLL的区别与使用

    原文地址: http://www.cppblog.com/amazon/archive/2011/01/01/95318.html 共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置 ...

  6. lib和dll的区别

    lib和dll的区别 共有两种库: 一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link librar ...

  7. vs cpp生成h文件_lib 和 dll 的区别、生成以及使用详解

    (给CPP开发者加星标,提升C/C++技能) 来源:tenoshttps://www.cnblogs.com/TenosDoIt/p/3203137.html [导读]:在日常开发中,我们只需要知道l ...

  8. LIB和DLL的区别与使用

    LIB和DLL的区别与使用 转载于:https://www.cnblogs.com/jingzhishen/p/7088698.html

  9. VS中的lib和dll的区别和使用

    LIB和DLL文件在创建工程项目时是必须要面对的,下面的文章讲述了如何添加LIB和DLL文件以及两者的区别. 1.加载lib/头文件 分两种方法: (1)适用于当前项目 1 第一步:项目->属性 ...

最新文章

  1. ueditor1.4.3配置过程(包含单独上传文件以及图片的使用)
  2. linux fall delay 10,Cell的Rise delay和Fall delay、Rise transition和fall transition
  3. 花了一晚上时间,终于把Python的基本用法归纳好了!
  4. 14、utf8和UTF-8在使用中的区别
  5. 2018热度上升最快的编程工具是什么?TensorFlow只排第11
  6. mac新手入门:在Mac上怎么使用夜览
  7. 基于 React.js + redux + bootstrap 的 RubyChina 示例
  8. [源码解读]position_estimator_inav_main解读(如何启动光流)
  9. 收藏、退出一气呵成,2019年机器之心干货教程都在这里了
  10. vivos9e防抖功能设置教程
  11. 百度地图,定位,添加图标
  12. 职场不接受Gap Year
  13. CSS学习笔记 01、CSS3基础知识学习
  14. java公路车的气嘴_自行车气嘴的分类、特性和打气的方法
  15. 【实战篇】37 # 如何使用 QCharts 图表库绘制常用数据图表?
  16. Linux系统安装过程详解
  17. 计算机系统的多级层次结构
  18. Nexus 05 第二种方式 使用Jenkins Nexus插件上传制品
  19. 【备份恢复】noarchive模式下使用增量备份恢复数据库
  20. python关键词 打标签详解_Python学习日记13|利用python制作简书首页热门文章关键词标签云...

热门文章

  1. MySQL----mysql_secure_installation 安全配置向导
  2. C# + PHP RSA保密通讯
  3. 全球10大B2B电子商务平台排行,这个网站只排第三!
  4. 2022最新Emlog新版导航源码 带用户中心
  5. Repeater的查询,添加,修改,删除
  6. Unity 中实现擦除功能
  7. Matlab:写入到 Diary 文件
  8. 知来路方知去处。坎坷已过,一马平川后必看的经典!——2018最新倾斜摄影建模与无人机航拍影像处理完美配置解决方案!
  9. 逻辑式编程语言极简实现(使用C#) - 1. 逻辑式编程语言介绍
  10. 佩戴骨传导耳机对耳朵有损害?不仅无损相比传统耳机优点有很多