我在Delphi XE2中有项目组,其功能是从包加载插件。我创建了这些项目:
PluginInterface.bpl
- 包含插件和MainForm接口的包
UClassManager.pas
- 插件管理员UPlugin.pas
- plugins interface MultiPlug2.exe
- 包含可配置菜单的主窗体
MainUnit.pas (*.dfm)
- MainForm(MDI所有者)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个Manager实例。
答案 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
常数。