4

我正在玩弄使用动态加载 BPL 并将对象实例从主应用程序传递到 BPL 中的方法的想法。这在应用程序和 BPL 使用的单元之间造成了问题。

我写了一个小的原型来做到这一点,并且很好奇 Delphi 如何在内部管理应用程序中定义的类与 BPL 之间的差异。

例如,说一个基本的 Widget 类,如:

TmyWidget = class
private
  fId:Integer;
  fDescription:String;
public
  procedure DoSomething1();
end;

现在应用程序和 BPL 是使用包含 TmyWidget 类的单元构建的。后来,TMyWidget 发生了一些变化,应用程序被重建,但 BPL 没有(反之亦然)。我添加了另一个方法 DoSomething2() 并在应用程序中创建了一个 TmyWidget 实例并将其传递给 BPL 进行处理并输入基本的例子,它奏效了。但它显然充满了潜在的问题。

如果另一个动态加载的 BPL 也使用 TmyWidget,那么事情会变得更加有趣。它似乎有效,但绝对感觉不理想。

主要问题是 - 通常如何在主应用程序和 DLL 或 BPL 之间传递对象?我以前从未尝试过,可能是有充分理由的,但我有这个想法适合这种方法......

我想最好的方法是序列化对象并将这些字节传递过来并在 DLL/BPL 中反序列化它,这个过程要注意主机和动态加载的模块之间的潜在版本差异,但我希望新的 SimpleSharedMem选项可能会在没有序列化开销的情况下带来这个新功能,但它似乎不是很有用,除非你严格保持应用程序和 dll 在任何共享代码更改上重建......但在这个原型中,应用程序将保持相当稳定并且动态加载的模块会随着添加到 TmyWidget 的功能而频繁更改。(服务器应用程序充当基于客户端请求构建 TmyWidget 的工厂,应用程序会将实例传递给各种模块进行处理。)

4

2 回答 2

10

...很好奇 Delphi 如何在内部管理应用程序中定义的类与 BPL 中定义的类之间的差异

Delphi 通过不允许它来管理它。您不能同时在多个包中拥有一个具有相同名称的单元:如果这样做,您会收到一条错误消息,内容类似于Package XYZ already contains ABC(一段时间内没有看到...)。由于类型名称包括单元名称,因此您不能在两个不同的包中具有相同的类型。除非它是由它的 GUID 定义的接口,但那是另一回事。

...通常如何在主应用程序和 DLL 或 BPL 之间传递对象?

您不将对象传递给 DLL,这不是一个好主意。当您需要将对象传递给 BPL 时,请确保将该 BPL 的基类定义为第三个 BPL。

例子。您的多态行为TmyWidget可能是使用一些虚拟方法定义的。确保您有一个TmyWidgetBase定义所有这些虚拟方法的TmyWidget类,从该基类派生您的所有 's 并传递具有 type 的对象TmyWidgetBase。确保TmyWidgetBase该类在它自己的包中。

当我尝试这样做时,我最终得到了一个很小的“引导程序”exe 和许多 BPL。基本上所有的逻辑都在 BPL 中,以方便传递对象。

于 2011-03-09T16:26:01.307 回答
7

我从事的一个项目已经成功使用了大量的运行时包十多年了,所以我将分享一些我处理包的经验。

正如 Cosmin 指出的那样,不同的包不能包含相同的单元。如果您使用隐式链接,通过将包添加到另一个包的requires子句或通过将包添加到项目选项中的运行时包列表中,编译器将为您完成工作并报告以下错误消息之一:

E2199: Packages '%s' and '%s' both contain unit '%s'(如果您的编译项目依赖于两个包含相同单元的包)

E2200: Package '%s' already contains unit '%s'(如果您编译的包包含一个单元,则该单元已包含在它所依赖的包之一中)

如果您使用显式链接,使用 LoadPackage,通常会在运行时尝试检查(尽管它可以被规避)并引发:

EPackageError: 无法加载包“%s”。它包含单元“%s”,它也包含在包“%s”中

解决这些错误并不是那么困难。

如果您有两个包都需要使用一个单元,只需让其中一个包含该单元,另一个需要第一个。 包依赖图

如果您有两个需要使用彼此包含的单元的包,则必须将这些单元移动到两者都可以依赖的新包中。 依赖图

隐式链接包的优点是您可以直接访问类定义,就好像它们是静态链接的一样。只需将一个单元添加到您需要使用它的单元的使用子句中。编译器和运行时环境负责解决所有问题。

显式链接的包将需要依赖于初始化部分中的类注册。

于 2011-03-10T17:35:32.310 回答