-
Notifications
You must be signed in to change notification settings - Fork 7
Home
Welcome to the PluginManager wiki!
The Plug-in architecture is composed of a set of Core APIs and many loadable modules providing additional features or services to an application, referred to as plug-ins.
This level of modularity has a number of benefits:
- Easier parallel feature development
- The ability to mix and match features
- Enable unit testing at module level
- Speed-up prototyping and foster code re-use
A plug-in is simply a code library that...
is linked/loaded at run-time.
- exposes one or more C++ interfaces. We call them Extensions
- requires zero or more C++ interfaces from other plug-ins. we call them Dependencies
Plug-ins generally provide some kind of service, feature or function. They often depend on other interfaces. Implementation of those interfaces are provided by other plug-ins.
The Plugin Manager loads all plugins (shared libraries) and connect the Extensions with the Dependencies. The list of plugin to be loaded is provided by a configuration file (.json file)
Json example:
{ "configuration": { "description": "Demo application", "author":"Nicolas Robert" }, "plugins":["../../plugins/libUniverseAnswerGeneratorPlugin", "../../plugins/libGeneratorManagerPlugin", "../../plugins/libDummyGeneratorPlugin"] }
Your interface must inherit IPluginInterface and provide an implementation for the id() and rttiMatch() method. note: make sure than you interface id is unique across all interfaces
class IGeneratorManager: public IPluginInterface
{
public:
virtual ~IGeneratorManager() {}
virtual QWidget* widget() = 0;
virtual InterfaceId id() const
{
return InterfaceId("IGeneratorManager");
}
virtual bool rttiMatch(const char *str) const
{
return (::strcmp(id().name().c_str(), str) == 0);
}
};Must inherit QObject along with your Interface.
Do not forget the Q_OBJECT macro.
The method addNumberGenerator() below will be called by the plugin to transmit the IPluginInterface given by the Plugin Manager.
class GeneratorManagerImpl: public QObject, public plugin::interfaces::IGeneratorManager
{
Q_OBJECT
public:
GeneratorManagerImpl();
~GeneratorManagerImpl();
QWidget* widget();
void addNumberGenerator(QSharedPointer<plugin::interfaces::INumberGenerator> gen)
{
m_gens.append(gen);
}
public slots:
void generateNumbers();
private:
QWidget *m_root;
QTextEdit *m_textEdit;
QList< QSharedPointer< plugin::interfaces::INumberGenerator> > m_gens;
};note: this Class inherits QObject because it has slots. It is not mandatory. See UniverseAnswerGeneratorPlugin as an example.
The Plugin itself must inherit IPluginLib.
First, set your interface as a singleton:
static QSharedPointer<GeneratorManagerImpl> generatorManager()
{
static QSharedPointer<GeneratorManagerImpl> theGeneratorManager;
if ( !theGeneratorManager ) {
theGeneratorManager.reset( new GeneratorManagerImpl() );
}
return theGeneratorManager;
}You must also declare:
- your extensions (The Interfaces for which your plugin will provide an implementation
- your dependencies (The interfaces that you plugin requires)
GeneratorManagerPlugin::GeneratorManagerPlugin()
{
m_extensions.push_back(new plugin::Extension(generatorManager()));
m_dependencies.push_back(new plugin::Dependency(0,plugin::DEPENDENCY_UNLIMITED,plugin::InterfaceId("INumberGenerator")));
}Finally, you should handle the dependencies that will be given to your plugin by the Plugin Manager:
void GeneratorManagerPlugin::connectExtension(QSharedPointer<plugin::interfaces::IPluginInterface> iface)
{
//cast away Tom!
QSharedPointer<plugin::interfaces::INumberGenerator> nbGen = qSharedPointerCast<plugin::interfaces::INumberGenerator>(iface);
generatorManager()->addNumberGenerator(nbGen);
}If you have more than one dependency, you should try to cast to all the required interfaces until you find the right one.
There is a cardinality notion when it comes to defining dependencies. You can have a optional dependency (0..n), or a hard one (1..1), (2..3) etc. IT can also be unlimited, and in this case, the Plugin Manager will provide all the implementation of a given interface.
Note: It must also inherit QObject. I will try to move this dependency up the tree in order to simplify the plugin creation.

