Plug-in API
5 min read
4 min read
4 min read
The Plugin Base Class
Plugin Base ClassA C++ plug-in is an instance of a class that implements the Ice::Plugin abstract base class:
namespace Ice{ class Plugin { public: virtual ~Plugin(); virtual void initialize() = 0; virtual void destroy() = 0; };}A plug-in object's lifecycle consists of four phases:
- Construction. Ice calls the plug-in factory during communicator initialization. Acquire resources here, but defer starting threads and using other plug-ins until
initialize. - Initialization. After constructing all plug-ins, Ice calls
initializein construction order. Factories inInitializationData.pluginFactoriesrun in list order, followed by plug-ins loaded through configuration. Use Ice.PluginLoadOrder to order the latter. A plug-in can use another plug-in after that plug-in has initialized. - Active use. The plug-in provides its services until the communicator is destroyed. Its implementation must handle concurrent calls when multiple threads use these services.
- Destruction. When the communicator is destroyed, Ice calls
destroyin reverse initialization order.
If the initialize method of a plug-in throws an exception, communicator initialization fails with PluginInitializationException. Ice does not call destroy on this plug-in: initialize must release the resources it acquired before throwing.
Plug-in Factory Function
In C++, a plug-in factory is a function with the following signature:
using PluginFactoryFunc = Ice::Plugin* (*)(const Ice::CommunicatorPtr& communicator, const std::string& name, const Ice::StringSeq& args);You can choose any name for the factory function of your plug-in. If you want to load this plug-in at runtime, you will need to export this function from the library and provide its name in configuration. Use C linkage to avoid name-mangling. For example:
extern "C" ICE_DECLSPEC_EXPORT Ice::Plugin* createPlugin( const Ice::CommunicatorPtr& communicator, const std::string& name, const Ice::StringSeq& args);The arguments to the function consist of the communicator that is in the process of being initialized, the name assigned to the plug-in, and any arguments that were specified in the plug-in's configuration.
Allocate the plug-in with new. Ice takes ownership of the pointer returned by the factory function.
Loading a Plug-in Using InitializationData
When your application depends on a plug-in, you should load this plug-in into your communicator by adding a factory for this plug-in to the pluginFactories field of your communicator’s InitializationData.
For example:
#include <Ice/Ice.h>#include <IceDiscovery/IceDiscovery.h>
Ice::InitializationData initData;initData.properties = Ice::createProperties(argc, argv);initData.pluginFactories = {IceDiscovery::discoveryPluginFactory()};
Ice::CommunicatorPtr communicator = Ice::initialize(initData);pluginFactories is a vector of:
struct PluginFactory{ /// The name of the plug-ins created by this factory. std::string pluginName;
/// The factory function. Ice::PluginFactoryFunc factoryFunc;};Ice creates the plug-ins in list order, each with the name given by its factory, before the plug-ins loaded through configuration. To pass arguments to one of these plug-ins, set the Ice.Plugin.Name property, where Name is the plug-in's name. Ice ignores the first token of the value, which holds the entry point of a plug-in loaded through configuration, and passes the remaining tokens to the factory. By convention, this first token is 1. For example:
Ice.Plugin.MyPlugin=1 arg1 arg2Managing Plug-ins
The plug-in manager of a communicator gives access to its plug-ins: call getPluginManager on the communicator, then getPlugin with the name of the plug-in. See PluginManager in the API reference.
To configure a plug-in through its own API before Ice initializes it, set Ice.InitPlugins to 0. Create the communicator, obtain the plug-in with getPlugin, configure it, and then call initializePlugins on the plug-in manager.
Transport Factories and Static Linking
The Ice C++ shared library registers the TCP, SSL, UDP, and WebSocket transports automatically. The static Ice library registers only TCP and SSL: when you link with this library, add Ice::udpPluginFactory() or Ice::wsPluginFactory() to pluginFactories for the UDP or WebSocket transport you need. The IceDiscovery and IceLocatorDiscovery plug-ins need UDP.
See Also
The Plugin Interface
Plugin InterfaceA C# plug-in is an instance of a class that implements the Ice.Plugin interface:
namespace Ice;
public interface Plugin{ void initialize(); void destroy();}A plug-in object's lifecycle consists of four phases:
- Construction. Ice calls the plug-in factory during communicator initialization. Acquire resources here, but defer starting threads and using other plug-ins until
initialize. - Initialization. After constructing all plug-ins, Ice calls
initializein construction order. Factories inInitializationData.pluginFactoriesrun in list order, followed by plug-ins loaded through configuration. Use Ice.PluginLoadOrder to order the latter. A plug-in can use another plug-in after that plug-in has initialized. - Active use. The plug-in provides its services until the communicator is destroyed. Its implementation must handle concurrent calls when multiple threads use these services.
- Destruction. When the communicator is destroyed, Ice calls
destroyin reverse initialization order.
If the initialize method of a plug-in throws an exception, communicator initialization fails with PluginInitializationException. Ice does not call destroy on this plug-in: initialize must release the resources it acquired before throwing.
Plug-in Factory
In C#, a plug-in factory is a class that implements the PluginFactory interface:
namespace Ice;
public interface PluginFactory{ string pluginName { get; }
Plugin create(Communicator communicator, string name, string[] args);}The arguments to the create method consist of the communicator that is in the process of being initialized, the name assigned to the plug-in, and any arguments that were specified in the plug-in's configuration.
Ice uses pluginName as the name of the plug-in when it creates a plug-in configured using InitializationData.pluginFactories (see below).
Loading a Plug-in Using InitializationData
When your application depends on a plug-in, you should load this plug-in into your communicator by adding a factory for this plug-in to the pluginFactories field of your communicator’s InitializationData.
For example:
var initData = new Ice.InitializationData{ properties = new Ice.Properties(ref args), pluginFactories = [new IceDiscovery.PluginFactory()]};
await using Ice.Communicator communicator = Ice.Util.initialize(initData);pluginFactories is a list of PluginFactory.
Ice creates the plug-ins in list order, each with the name given by its factory, before the plug-ins loaded through configuration. To pass arguments to one of these plug-ins, set the Ice.Plugin.Name property, where Name is the plug-in's name. Ice ignores the first token of the value, which holds the entry point of a plug-in loaded through configuration, and passes the remaining tokens to the factory. By convention, this first token is 1. For example:
Ice.Plugin.MyPlugin=1 arg1 arg2Managing Plug-ins
The plug-in manager of a communicator gives access to its plug-ins: call getPluginManager on the communicator, then getPlugin with the name of the plug-in. See PluginManager in the API reference.
To configure a plug-in through its own API before Ice initializes it, set Ice.InitPlugins to 0. Create the communicator, obtain the plug-in with getPlugin, configure it, and then call initializePlugins on the plug-in manager.
See Also
The Plugin Interface
Plugin InterfaceA Java plug-in is an instance of a class that implements the com.zeroc.Ice.Plugin interface:
package com.zeroc.Ice;
public interface Plugin { void initialize(); void destroy();}A plug-in object's lifecycle consists of four phases:
- Construction. Ice calls the plug-in factory during communicator initialization. Acquire resources here, but defer starting threads and using other plug-ins until
initialize. - Initialization. After constructing all plug-ins, Ice calls
initializein construction order. Factories inInitializationData.pluginFactoriesrun in list order, followed by plug-ins loaded through configuration. Use Ice.PluginLoadOrder to order the latter. A plug-in can use another plug-in after that plug-in has initialized. - Active use. The plug-in provides its services until the communicator is destroyed. Its implementation must handle concurrent calls when multiple threads use these services.
- Destruction. When the communicator is destroyed, Ice calls
destroyin reverse initialization order.
If the initialize method of a plug-in throws an exception, communicator initialization fails with PluginInitializationException. Ice does not call destroy on this plug-in: initialize must release the resources it acquired before throwing.
Plug-in Factory
In Java, a plug-in factory is a class that implements the PluginFactory interface:
package com.zeroc.Ice;
public interface PluginFactory { String getPluginName(); Plugin create(Communicator communicator, String name, String[] args);}The arguments to the create method consist of the communicator that is in the process of being initialized, the name assigned to the plug-in, and any arguments that were specified in the plug-in's configuration.
Ice uses the value returned by getPluginName() as the name of the plug-in when it creates a plug-in configured using InitializationData.pluginFactories (see below).
Loading a Plug-in Using InitializationData
When your application depends on a plug-in, you should load this plug-in into your communicator by adding a factory for this plug-in to the pluginFactories field of your communicator’s InitializationData.
For example:
InitializationData initData = new InitializationData();initData.properties = new com.zeroc.Ice.Properties(args);initData.pluginFactories = java.util.List.of(new com.zeroc.IceDiscovery.PluginFactory());
try (Communicator communicator = new Communicator(initData)) { // Use the communicator.}pluginFactories is a list of com.zeroc.Ice.PluginFactory.
Ice creates the plug-ins in list order, each with the name given by its factory, before the plug-ins loaded through configuration. To pass arguments to one of these plug-ins, set the Ice.Plugin.Name property, where Name is the plug-in's name. Ice ignores the first token of the value, which holds the entry point of a plug-in loaded through configuration, and passes the remaining tokens to the factory. By convention, this first token is 1. For example:
Ice.Plugin.MyPlugin=1 arg1 arg2Managing Plug-ins
The plug-in manager of a communicator gives access to its plug-ins: call getPluginManager on the communicator, then getPlugin with the name of the plug-in. See PluginManager in the API reference.
To configure a plug-in through its own API before Ice initializes it, set Ice.InitPlugins to 0. Create the communicator, obtain the plug-in with getPlugin, configure it, and then call initializePlugins on the plug-in manager.