0

我在 Delphi XE2 中有一个项目组,它的功能是从包中加载插件。我创建了这些项目:

  • PluginInterface.bpl– 带有插件和 MainForm 接口的包
    • UClassManager.pas- 插件管理器
    • UPlugin.pas– 插件界面
  • MultiPlug2.exe- 带有可配置菜单的主窗体
    • MainUnit.pas (*.dfm)– MainForm(MDI 所有者)
    • 等等... – 一些形式(例如 Splash、数据库登录)
  • TestPlugin.bpl– 测试插件
    • UTestPlugin.pas– 测试插件接口
    • TestForm.pas (*.dfm)– 测试表(MDI 儿童)。

这里有一些清单

我有问题

procedure TMainForm.RefreshPluginsList;
var
  Pair: TPair<string, TMenuItem>;
  I: integer;
begin
  for I := 0 to ClassManager.Count - 1 do
    RegisterPlugin(ClassManager[i]);
  for Pair in MenuDict do
    Pair.Value.Visible := Pair.Value.Count > 0;
end;

whereClassManager.Count总是零,所以RegisterPlugin永远不会被调用。我应该怎么做才能使其成为 1 并正确注册我的插件?

Handles.Add(LoadPackage('PluginInterface.bpl'))编辑:我按照建议删除了。这没有帮助。我在跟踪程序时看到了 2 个 Manager 实例。

4

1 回答 1

2

看起来您在不使用 BPL 的情况下制作了 EXE -“使用运行时包”已关闭,或者通用共享插件接口包不在“必需”列表中。

另一个可能(但不太可能)的原因是使用弱包装 - 这也意味着UClassManager单元(包括 ClassManager 函数和变量的额外实例)将被复制到每个二进制文件中。 http://docwiki.embarcadero.com/RADStudio/XE5/en/Using_the_Weak_Packaging_Directive

您不能也不应该动态加载该包 - 因为到 UClassManager 的链接应该已经在编译时建立。因此LoadPackage('PluginInterface.bpl'),充其量是多余的,最坏的情况是破坏,应该被删除。

我认为你没有这样做,所以现在你有两个 ClassManager 实例——一个在 EXE 中,另一个在 DLL 中。您可以检查它是否发出命令,例如

ShowMessage(IntToHex(Integer(Pointer(ClassManager()))))

在 EXE 和 BPL 中查看这些实例的真实情况。

阅读有关使用运行时包的手册或一些 Delphi 教科书。几个例子:

正确构建项目后,您可以检查您的 EXE 是否确实使用UClassManager了 BPL 中的单元,而不是制作自己的独立克隆。

你可以查看EXE的导入函数表和DLL依赖树,看看EXE是否真的UClassManager从正确的BPL调用初始化函数。一些允许这样做的程序:

另一种选择是使用 Delphi IDE 菜单中的“Project / Analyze”命令并检查“show packages”选项以查看哪个二进制文件包含哪个单元。您可以在安装作为 Jedi CodeLib 的一部分的项目分析器包后找到此命令,网址为http://jcl.sf.net


PS。由于您使用 XE2,我建议您避免使用TList二进制指针和危险的未经检查的类型转换。你最好把你TClassManager的老旧TClassList(已经存在于 Delphi 5 甚至更早)或基于TList<TPlugin>

聚苯乙烯。由于您使用 XE2 并动态加载/卸载 BPL,因此请避免在包中使用类型常量(或预初始化变量)array [...] of string。他们正在被摧毁。我有一些想法为什么会发生这种情况,以及它是如何在 XE3/4 中修复的,但我有点懒于实施补丁。为此,我刚刚切换到array [....] of PChar常量。

于 2013-10-22T07:51:25.700 回答