加载的BPL插件列表假装为空,尽管实际上已经封装了包

时间:2013-10-21 10:38:46

标签: delphi plugins package bpl

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

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

Here are some listings

我有

的问题
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;

其中ClassManager.Count始终为零,因此永远不会调用RegisterPlugin。我应该怎么做才能使它成为1并正确注册我的插件?

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

1 个答案:

答案 0 :(得分:2)

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

  

另一种可能(但不太可能)的原因是使用弱包装 -   这也意味着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中,看看那些实例到底是什么。

阅读有关使用Runtime Packages的手册或一些Delphi教科书。几个例子:

在正确建立项目后,您可以检查您的EXE是否实际上使用了BPL中的单位UClassManager,而不是自己独立克隆它。

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

还有一个选项是使用Delphi IDE菜单中的“Project / Analyze”命令并选中“show packages”选项以查看哪个二进制文件包含哪个单元。您可以在安装Project Analyzer软件包之后找到此命令,该软件包是Jedi CodeLib的一部分http://jcl.sf.net


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

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