>我在Delphi XE2中有项目组,其功能是从包加载插件。我创建了这些项目:
-
PluginInterface.bpl
– 带有插件和 MainForm 接口的包-
UClassManager.pas
– 插件管理器 -
UPlugin.pas
– 插件界面
-
-
MultiPlug2.exe
– 带有可配置菜单的主窗体-
MainUnit.pas (*.dfm)
– 主窗体(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;
其中 ClassManager.Count
始终为零,因此从不调用RegisterPlugin
。我应该怎么做才能使其成为 1 并正确注册我的插件?
编辑:我按照建议删除了Handles.Add(LoadPackage('PluginInterface.bpl'))
。这无济于事。我在跟踪程序时看到 2 个管理器实例。
看起来您在不使用 BPL 的情况下制作了 EXE——要么"使用运行时包"已关闭,要么通用共享插件接口包不在"必需"列表中。
另一个可能(但不太可能)的原因是使用弱包装 - 这也意味着
UClassManager
单元(包括额外的实例 类管理器函数和变量)将被复制到每个二进制文件中。 http://docwiki.embarcadero.com/RADStudio/XE5/en/Using_the_Weak_Packaging_Directive
你不能也不应该动态加载该包 - 因为指向UClassManager的链接应该已经在编译时建立。因此,LoadPackage('PluginInterface.bpl')
充其量是多余的,最坏的情况是破坏,应该删除。
我认为你没有这样做,所以现在你有两个类管理器实例 - 一个在 EXE 中,另一个在 DLL 中。您可以检查它是否发出命令,例如
ShowMessage(IntToHex(Integer(Pointer(ClassManager()))))
在 EXE 和两个 BPL 中,看看这些实例到底是什么。
阅读有关使用运行时包的手册或一些 Delphi 教科书。几个例子:
- http://www.obsof.com/delphi_tips/DL613.html
- http://pluginmgr.dennislandi.com/
- 在 Delphi XE2 上使用运行时包进行构建
- 如何将德尔福项目正确地划分为 BPL?
- 如何从可执行文件调用 bpl 中的 Delphi 函数?
- 如何在Windows/Delphi中编程插件?
- http://delphi.about.com/od/objectpascalide/l/aa012301a.htm
- https://groups.google.com/forum/#!topic/borland.public.delphi.vcl.components.writing/E_HyoAiai28
正确构建项目后,您可以检查您的 EXE 是否实际使用了 BPL 中的单元UClassManager
,而不是制作自己的独立克隆。
您可以查看 EXE 的导入函数表和 DLL 依赖树,以查看 EXE 是否真的从正确的 BPL 调用UClassManager
初始化函数。一些程序允许这样做:
- http://wincmd.ru/plugring/fileinfo.html(和 http://www.totalcmd.net/plugring/fileinfo.html)
- http://ntcore.com/exsuite.php
- http://ru.wikipedia.org/wiki/Dependency_Walker
另一个选项是使用Delphi IDE菜单中的"项目/分析"命令,并选中"显示包"选项以查看哪个二进制文件包含哪个单元。您可以在安装项目分析器包后找到此命令,该包是Jedi CodeLib的一部分,http://jcl.sf.net
附言。由于您使用的是 XE2,因此我建议您避免将TList
与二进制指针和危险的未经检查的类型转换一起使用。你最好把你的TClassManager
建立在古老的TClassList
(在Delphi 5甚至更早)或TList<TPlugin>
的基础上
.PPS。由于您使用的是 XE2 并动态加载/卸载 BPL,因此请在包中避免使用array [...] of string
类型的常量(或预初始化的变量)。他们正在被摧毁。我有一些想法为什么会发生这种情况以及如何在 XE3/4 中修复它,但我有点懒得实现补丁。为此,我只是切换到array [....] of PChar
常量。