Managing Plugin Instances (Delphi)
The key component of a Hydra host application is the module manager. For VCL projects you can use the THYModuleManager component and for FireMonkey the THYFMXModuleManager.
These components provide several methods that allow you to manage plugin instances, so let's take a look at these.
Creating new instances
The module manager has three different methods to create a new instance of the plugin:
CreateInstance
- Creates an instance of the plugin with the specified name and returns a reference to anIInterface
.CreateVisualPlugin
- Creates an instance of the visual plugin with the specified name and returns a reference to the IHYVCLVisualPlugin. It can also automatically show the plugin in the provided container.CreateNonVisualPlugin
- Creates an instance of a non-visual plugin with the specified name and returns a reference to the IHYVCLNonVisualPlugin.
The following example shows how to create an instance of a visual plugin:
TMainForm = class(TForm)
[..]
private
fVisualPlugin: IHYVCLVisualPlugin;
end;
[..]
procedure TMainForm.FormCreate(Sender: TObject);
begin
ModuleManager.LoadModule('ModuleName.dll');
ModuleManager.CreateVisualPlugin('VisualPluginName', fVisualPlugin, Panel1);
end;
TMainForm = class(TForm)
[..]
private
fVisualPlugin: IHYFMXVisualPlugin;
end;
[..]
procedure TMainForm.FormCreate(Sender: TObject);
begin
ModuleManager.LoadModule('ModuleName.dll');
ModuleManager.CreateVisualPlugin('VisualPluginName', fVisualPlugin, Panel1);
end;
TMainForm = class(TForm)
[..]
private
fVisualPlugin: IHYCrossPlatformVisualPlugin;
end;
[..]
procedure TMainForm.FormCreate(Sender: TObject);
var
Temp: IInterface;
begin
ModuleManager.LoadModule('ModuleName.dll');
ModuleManager.CreateInstance('VisualPluginName', Temp);
if Supports(Temp, IHYCrossPlatformVisualPlugin, fVisualPlugin) then
fVisualPlugin.ShowParented(Panel1.Handle);
end;
You can do the same thing by using the CreateInstance
method:
procedure TMainForm.FormCreate(Sender: TObject);
var
Temp: IInterface;
begin
ModuleManager.LoadModule('ModuleName.dll');
ModuleManager.CreateInstance('VisualPluginName', Temp);
if Supports(Temp, IHYVCLVisualPlugin, fVisualPlugin) then
fVisualPlugin.ShowParented(Panel1);
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
Temp: IInterface;
begin
ModuleManager.LoadModule('ModuleName.dll');
ModuleManager.CreateInstance('VisualPluginName', Temp);
if Supports(Temp, IHYFMXVisualPlugin, fVisualPlugin) then
fVisualPlugin.ShowParented(Panel1);
end;
procedure TMainForm.FormCreate(Sender: TObject);
var
Temp: IInterface;
begin
ModuleManager.LoadModule('ModuleName.dll');
ModuleManager.CreateInstance('VisualPluginName', Temp);
if Supports(Temp, IHYCrossPlatformVisualPlugin, fVisualPlugin) then
fVisualPlugin.ShowParented(Panel1.Handle);
end;
Lifetime
By default all Hydra plugins use reference counting to manage the plugin's life, and when the number of references reaches zero, the plugin and all of its resources are freed.
Hydra does not directly control the plugin's lifetime, so it's the job of the user's code to store the plugin's references to keep them alive. Take a look at the following code:
TMainForm = class(TForm)
[..]
private
fVisualPlugin: IHYVCLVisualPlugin;
end;
ModuleManager.CreateVisualPlugin('VisualPluginName', fVisualPlugin, Panel1);
In this snippet, we are using the fVisualPlugin
field to store the reference to the plugin instance and keep the plugin alive.
Instance References
When you create a plugin, Hydra stores a weak reference to the instance. Since all those references are weak, they won't prevent the plugin from being destroyed. You can use them to get access to plugin instances in some scenarios, however, please keep in mind that they are not guaranteed to be alive, so use them with extreme caution.
- property
InstanceCount
- Returns the number of instances - property
Instances[Index]
- Returns a reference (IHYVCLPlugin) with a specified index
For example:
var
Resources: IMyCustomResources;
begin
if Supports(ModuleManager.Instances[0], IMyCustomResources, Resources) then
Resources.LoadResource('MyCustomResource');
end;
Tracking References
In some scenarios using a variable for a single instance isn't the best approach, so you need something that can help you track references.
Delphi provides a special class called TInterfaceList
, which is designed to store a list of interfaces and manage their reference count properly.
For example:
TMainForm = class(TForm)
[..]
private
fInterfaces: TInterfaceList;
end;
[..]
procedure TMainForm.FormCreate(Sender: TObject);
begin
fInterfaces := TInterfaceList.Create;
end;
procedure TMainForm.NewInstanceClick(Sender: TObject);
var
Temp: IHYNonVisualPlugin;
begin
ModuleManager.CreateNonVisualPlugin('NonVisualPluginName', Temp);
fInterfaces.Add(Temp as IInterface);
end;
fInterfaces.Add
will store the interface in the list and keep a reference to this instance until it is removed.
Destroying Instances
In general, "destroying an instance" means decreasing the reference count to zero. This can be done in a couple of ways:
TMainForm = class(TForm)
[..]
private
fVisualPlugin: IHYVisualPlugin;
end;
{1} fVisualPlugin := nil;
{2} fVisualPlugin._Release;
{3} ModuleManager.ReleaseInstance(fVisualPlugin);
- Assign
nil
to an instance. - Call the
_Release
method. The first and second method are doing exactly the same thing. - Use the
ReleaseInstance
method of the module manager. This not only releases the instance, but also removes it from the internal list of instances.
All three ways are valid and can be used in your own applications, however, only when you use the ReleaseInstance
method, it is guaranteed that the instance will be removed from the module manager's instance list.
Please note that you must release all instances of a plugin before unloading the module, otherwise Hydra will throw an exeption.