简体   繁体   English

使用BPL加载Delphi对象运行时

[英]Loading a Delphi Object Run Time using BPL

I have a class in a unit. 我有一个单元课。 Usually, when I changed the algorithm of its methods, I have to recompile it and deliver the patch as a whole. 通常,当我更改其方法的算法时,我必须重新编译它并整体交付补丁。 I think to create the instance of the class using DLL. 我认为使用DLL创建类的实例。 After searching in delphi.about.com, I found that instead of using DLL, I can use BPL. 在delphi.about.com中搜索后,我发现可以使用BPL而不是使用DLL。 It is a DLL for Delphi. 它是Delphi的DLL。 The problem is almost all examples I found is only telling how to export a function. 问题是我发现的几乎所有示例都只是在告诉如何导出函数。 I want to dynamically load the BPL, and whenever I replace the BPL, I can get the latest algorithm of the class, not only the functions I export. 我想动态地加载BPL,每当替换BPL时,我都可以获得类的最新算法,而不仅仅是导出的函数。

Article I have read: 我读过的文章:
- http://delphi.about.com/od/objectpascalide/a/bpl_vs_dll.htm -http://delphi.about.com/od/objectpascalide/a/bpl_vs_dll.htm
- Plugins system for Delphi application - bpl vs dll? -Delphi应用程序的插件系统-bpl vs dll?
- http://delphi.about.com/library/weekly/aa012301a.htm -http://delphi.about.com/library/weekly/aa012301a.htm

Any URL or SAMPLE how to create a BPL from scratch to encapsulate a component or a class is greatly appreciated. 任何URL或SAMPLE如何从头开始创建BPL来封装组件或类都是非常感激的。


Dear Guru, 亲爱的大师,

Suppose I have code like this: 假设我有这样的代码:

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.

I want to export all public methods of A. How to make it a DLL? 我想导出A的所有公共方法。如何使其成为DLL? How to use it from another unit where to import it? 如何从另一个单元中将其导入到哪里? let's say: 比方说:

 var a: A;

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

A is not declared in the unit (it is in the DLL). 在单元中未声明A(它在DLL中)。 Please advise. 请指教。


Hurray. 欢呼。 I got it last night. 昨晚我知道了。 All I have to do is make the object implement an interface which is used in the caller unit to catch the instance of object returned by the DLL. 我要做的就是使对象实现一个接口,该接口在调用方单元中用于捕获DLL返回的对象的实例。

Thank you all. 谢谢你们。

Mason nailed it already, but let me elaborate on why BPLs aren't what you are looking for. 梅森已经把它钉牢了,但是让我详细说明为什么BPL不是您想要的。 BPLs are a means for the Delphi IDE to load components that share the same memory manager and RTL. BPL是Delphi IDE加载共享相同内存管理器和RTL的组件的一种方式。 (Type identity works almost transparently using BPLs) (类型标识几乎可以使用BPL透明地工作)

However, the dependencies you are getting tied up in are almost always unacceptable. 但是,被捆绑的依赖关系几乎总是不可接受的。 Except for the IDE, which cannot handle different versions of RTL and VCL anyway. 除了IDE,IDE仍然无法处理不同版本的RTL和VCL。

When you pass only interface references between your application and its DLLs, then you don't have to share RTL, VCL or shared packages at all. 当您仅在应用程序及其DLL之间传递接口引用时,则根本不必共享RTL,VCL或共享包。

It also means that you could write some DLLs in another language (C++, C#, FPC, another Delphi version), and still use objects. 这也意味着您可以用另一种语言(C ++,C#,FPC,另一种Delphi版本)编写某些DLL,而仍然使用对象。 Which can be tempting when you don't want to port your main app but still want to use existing libraries that are not available for Delphi, or your version of Delphi. 当您不想移植主应用程序但仍想使用Delphi或您的Delphi版本不可用的现有库时,这可能很诱人。

The problem with putting a class in an external file is that your main application needs to know some way to refer to it. 将类放在外部文件中的问题是您的主应用程序需要知道某种引用它的方法。 It will either have to descend from a base class that exposes all the methods you need as virtual methods, or implement an interface that contains all the functionality you need from it. 它要么必须继承于将您需要的所有方法公开为虚拟方法的基类,要么必须实现一个包含您需要的所有功能的接口。

If you already know what the interface of the object should look like, and all you're changing is implementation details such as internal algorithms, probably the easiest thing would be to make your class implement an interface and put it in a DLL that exports a function that returns an instance of this interface. 如果您已经知道对象的界面应该是什么样子,而您所要做的只是更改实现细节(例如内部算法),那么最简单的方法可能是使您的类实现一个接口并将其放在一个DLL中,该DLL可以导出返回此接口实例的函数。 That way you don't need to worry about breaking your app up into packages, which can be a real hassle. 这样一来,您就不必担心将您的应用程序分解为多个程序包,这可能是一个真正的麻烦。

I see nothing in your problem description suggesting you would need to explicitly export anything from the package or that you would need to load it dynamically at run time. 我在问题描述中什么都没有看到,这表明您需要从包中显式导出任何内容,或者需要在运行时动态加载它。 Instead, it's enough that your functions reside in a run-time package that can be replaced separately from the main program. 相反,您的函数驻留在可以与主程序分开替换的运行时包中就足够了。

Start a new package project and move your class's unit into that project along with any other units it depends on. 启动一个新的包项目,并将您班级的单元以及它所依赖的任何其他单元移到该项目中。 Compile the project. 编译项目。 If the compiler warns about "implicitly including" any other units, add those to the package, too. 如果编译器警告“隐式包括”任何其他单元,请将它们也添加到程序包中。

Now, remove any of the package units from the EXE project. 现在,从EXE项目中删除所有程序包单元。 There should be no units that are members of both projects. 这两个项目都不应有任何单位。 Next, turn on the "build with run-time packages" checkbox in your EXE's project options. 接下来,打开EXE项目选项中的“使用运行时程序包构建”复选框。 Add your package to the semicolon-separated list of package names. 将您的软件包添加到以分号分隔的软件包名称列表中。 The RTL and VCL packages will probably also be on that list. RTL和VCL软件包也可能会在该列表中。

Compile both projects, and you're done. 编译两个项目,您就完成了。

If you make changes to your class implementation, you can recompile the package only and send a new version to customers. 如果您对类的实现进行了更改,则只能重新编译该包并将新版本发送给客户。 The program will automatically get the new changes when you replace the original file with the new one. 当您用新文件替换原始文件时,该程序将自动获得新更改。 The package is listed in the program's import table, so the OS will automatically load the BPL file when it loads the EXE. 该程序包在程序的导入表中列出,因此,操作系统在加载EXE时会自动加载BPL文件。 The EXE doesn't need to run any special code to load the package. EXE不需要运行任何特殊代码即可加载程序包。

Delphi can create DLL to export functions or BPL to export component. Delphi可以创建DLL来导出功能,或者创建BPL来导出组件。

You can create component, compile it (use the same compiler settings as in your main app), and Delphi will create .bpl. 您可以创建组件,对其进行编译(使用与主应用程序相同的编译器设置),然后Delphi将创建.bpl。 Then import this component to Delphi and compile your app with this compomponent as a package. 然后将此组件导入Delphi,并使用该组件作为包编译您的应用程序。

My experience with components created with Delphi 4 proved that one, big application is more reliable than application with separate .bpls. 我对使用Delphi 4创建的组件的经验证明,一个大型应用程序比带有单独的.bpls的应用程序更可靠。 It was multithreaded server and it worked fine if compiled standalone, while crashed after short time if compiled with packages. 它是多线程服务器,如果独立编译,效果很好,但是如果使用软件包编译,则在短时间后崩溃。 I hope newer versions of Delphi improved in this area. 我希望较新版本的Delphi在此方面有所改进。

Be aware of memory management (in app do not free memeory allocated in package and vice versa) and compiler settings. 注意内存管理(在应用程序中,不要释放程序包中分配的内存,反之亦然)和编译器设置。

If you like about.com then this link will be useful: Introduction to Packages; 如果您喜欢about.com,则此链接将非常有用 BPLs are special DLLs! BPL是特殊的DLL!

BPLs have their usage. BPL有其用法。 For example if you have to make a very huge application like an Erp, you need to try to use BPLs seriously. 例如,如果您必须制作一个非常大的应用程序(如Erp),则需要尝试认真使用BPL。

In the other hand, BPLs aren't responsible of crashing applications. 另一方面,BPL对崩溃的应用程序不负责。 Bad usage of BPLs does it. BPL的使用不当会造成这种情况。

you can try the MAF Components, they handle plugins and much more for you without extra code. 您可以尝试MAF组件,它们可以处理插件,并且为您提供更多功能,而无需额外的代码。 Comes with tutorials and a demo application with source. 随附教程和带有源代码的演示应用程序。

http://www.maf-components.com http://www.maf-components.com

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM