【问题标题】:Loading a Delphi Object Run Time using BPL使用 BPL 加载 Delphi 对象运行时
【发布时间】:2009-11-09 11:01:54
【问题描述】:

我在一个单元有一堂课。通常,当我更改其方法的算法时,我必须重新编译它并将补丁作为一个整体交付。 我认为使用 DLL 创建类的实例。在delphi.about.com上搜索后,发现不用DLL,可以用BPL。它是 Delphi 的 DLL。问题是我发现的几乎所有示例都只是告诉如何导出函数。 我想动态加载BPL,每当我替换BPL时,我都能得到该类的最新算法,而不仅仅是我导出的函数。

我读过的文章:
- http://delphi.about.com/od/objectpascalide/a/bpl_vs_dll.htm
- Plugins system for Delphi application - bpl vs dll?
- http://delphi.about.com/library/weekly/aa012301a.htm

非常感谢任何如何从头开始创建 BPL 以封装组件或类的 URL 或 SAMPLE。


尊敬的大师,

假设我有这样的代码:

unit unitA;

interface

type
  B = class(TObject)
  public
    procedure HelloB;
  end;

  A = class(TObject)
  public
    function GetB: B;
    function HelloA: String;
    procedure Help;
  end;

  implementation

  uses
      Dialogs;

  { B }

   procedure B.HelloB;
   begin
     ShowMessage('B');
   end;

  { A }

  function A.GetB: B;
  begin
    Result := B.Create;
  end;

  function A.HelloA: String;
  begin
    Result := 'Hello, this is A';
  end;

  procedure A.Help;
  begin
    //do something
  end;

  end.

我想导出A的所有公共方法。如何使它成为DLL? 如何使用它从另一个单元导入它? 比方说:

 var a: A;

 a := A.Create;
 a.GetB;
 showMessage(a.HelloA);

A 未在单元中声明(它在 DLL 中)。 请指教。


万岁。我昨晚收到了。我所要做的就是让对象实现一个接口,该接口在调用者单元中用于捕获 DLL 返回的对象实例。

谢谢大家。

【问题讨论】:

  • 各位,BPL 可以和 Java Class Loader 相提并论吗? Delphi 中是否有与 Java 中的类加载器类似的功能?
  • @WishKnew:简而言之,BPL 是一个具有额外功能的 DLL。此额外功能有助于共享资源,例如对象和依赖项。

标签: delphi dll package bpl


【解决方案1】:

Mason 已经搞定了,但让我详细说明为什么 BPL 不是您想要的。 BPL 是 Delphi IDE 加载共享相同内存管理器和 RTL 的组件的一种方法。 (类型标识使用 BPL 几乎可以透明地工作)

但是,您所依赖的依赖项几乎总是不可接受的。除了 IDE,它无论如何都不能处理不同版本的 RTL 和 VCL。

当您只在应用程序及其 DLL 之间传递接口引用时,您根本不必共享 RTL、VCL 或共享包。

这也意味着您可以用另一种语言(C++、C#、FPC、另一个 Delphi 版本)编写一些 DLL,并且仍然使用对象。当您不想移植主应用但仍想使用 Delphi 或您的 Delphi 版本不可用的现有库时,这可能很诱人。

【讨论】:

  • 好的,现在我大胆地研究如何使用 DLL 来完成它。 Tq。但是COM呢?你有什么cmets如何使用COM方法解决这个问题?
  • COM 是完全不同的动物,尽管通过 Delphi 的 COM 被大大简化了,但它仍然大大超出了 stackoverflow 线程的范围。
【解决方案2】:

将类放在外部文件中的问题是您的主应用程序需要知道某种方式来引用它。它要么必须从将您需要的所有方法公开为虚拟方法的基类继承下来,要么实现一个包含您需要的所有功能的接口。

如果您已经知道对象的接口应该是什么样子,并且您要更改的只是内部算法等实现细节,那么最简单的方法可能是让您的类实现一个接口并将其放入 DLL导出一个返回此接口实例的函数。这样您就不必担心将您的应用拆分成多个包,这可能会很麻烦。

【讨论】:

  • 好吧.. 我仍然需要阅读有关 DLL 的信息。我认为 DLL 只是封装程序/函数,而不是对象。我不知道它可以返回 TObject 的后代或接口的实例。是的,就我现在而言,界面永远不会改变。其实它是一个有很多功能的计算器。我从少量功能开始,现在功能越来越多。它只是调用 Evaluate(expression: String) 并以 String 形式返回结果。当表达式越来越丰富时,我不想替换exe,而只想替换Calculator类。时长
【解决方案3】:

我在您的问题描述中没有看到任何内容表明您需要从包中显式导出任何内容,或者您​​需要在运行时动态加载它。相反,将您的函数驻留在一个运行时包中就足够了,该包可以与主程序分开替换。

开始一个新的包项目,并将你的班级单元连同它所依赖的任何其他单元一起移动到该项目中。编译项目。如果编译器警告“隐式包含”任何其他单元,也将它们添加到包中。

现在,从 EXE 项目中删除任何包单元。不应有任何单位同时是这两个项目的成员。接下来,在您的 EXE 项目选项中打开“使用运行时包构建”复选框。将您的包添加到以分号分隔的包名称列表中。 RTL 和 VCL 包可能也在该列表中。

编译这两个项目,你就完成了。

如果您对类实现进行了更改,则只能重新编译包并将新版本发送给客户。当您用新文件替换原始文件时,程序将自动获取新的更改。该包在程序的导入表中列出,因此操作系统在加载 EXE 时会自动加载 BPL 文件。 EXE 不需要运行任何特殊代码来加载包。

【讨论】:

  • 好的,我会尝试 BPL 和 DLL。谢谢!
  • @Rob:我正在尝试,但它不起作用。在在这里找到您的帖子之前,我发布了一个问题。见:stackoverflow.com/questions/17012217/…
【解决方案4】:

Delphi 可以创建 DLL 来导出函数或 BPL 来导出组件。

您可以创建组件,编译它(使用与主应用程序相同的编译器设置),Delphi 将创建 .bpl。然后将此组件导入 Delphi 并使用此组件作为包编译您的应用程序。

我使用 Delphi 4 创建组件的经验证明,大型应用程序比具有单独 .bpls 的应用程序更可靠。它是多线程服务器,如果独立编译它可以正常工作,但如果使用包编译,它会在短时间内崩溃。我希望新版本的 Delphi 在这方面有所改进。

注意内存管理(在应用程序中不要释放包中分配的内存,反之亦然)和编译器设置。

如果您喜欢 about.com,那么此链接将很有用:Introduction to Packages; BPLs are special DLLs!

【讨论】:

  • 如果您遵守规则并为应用程序和 BPL 使用相同的内存管理器,那么在与分配内存不同的模块中释放内存应该不是问题。如果你没有遵守这些规则,我并不惊讶你发现你的单体应用程序更稳定。不过,您的经验并不能证明缺乏可靠性。为此,您必须首先证明您没有犯任何错误。
  • 我了解内存管理并警告组件创建者/用户在组件和应用程序中使用相同的内存管理器和相同的编译器选项。就我而言,我使用了相同的内存管理器。 BPL 在单线程应用程序中运行良好,但在多线程应用程序中我发现了神秘的崩溃。它们在一段时间后出现(有时在 15 分钟后,有时在一个小时后)。当我在没有包的情况下编译我的服务器应用程序时,它们消失了。这是 Delphi 4 的时代,所以现在是史前时代。
【解决方案5】:

BPL 有其用途。例如,如果您必须制作像 Erp 这样非常庞大的应用程序,则需要认真尝试使用 BPL。

另一方面,BPL 不负责崩溃应用程序。错误地使用 BPL 就可以做到这一点。

【讨论】:

  • BPL 引入了有史以来最糟糕的版本控制地狱。您不仅依赖于您的编译器和 RTL/VCL 版本,不,还依赖于所有共享包中每个 DCU 的版本。对于这种共享代码的使用,你指的是,DLL,通过接口共享对象)是最稳定、可互操作的(无需在 Delphi 中编写 DLL,可以是 C#、C++、FPC 等)和无痛路径,除了单一的 exes。
【解决方案6】:

您可以尝试使用 MAF 组件,它们无需额外代码即可为您处理插件等等。附带教程和带有源代码的演示应用程序。

http://www.maf-components.com

【讨论】:

  • 抱歉,我正在寻找原生解决方案,不涉及任何其他付费解决方案。还是谢谢你。
  • 似乎 MAF 组件kapput,不再可见。他们倒闭了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2011-11-09
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
  • 2012-08-07
相关资源
最近更新 更多