OpenAB  1.0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
The Plugin Interface

List of available plugins

For complete list of available plugins and their configuration see Plugin List

Overview

The plugin interface "OpenAB_Plugin" is used to implement a Plugin Based mechanism useful to keep an abstraction layer between the core and the plugins implemented.

It allow the main program to define a generic interface implemented by all the plugins that may or not be loaded runtime.

plugin.overview.001.png
Overview

Implementation Detail

The Plugin Template (plugin.hpp) is basically a template library helper that must be used to create any kind of generic plugin.

Once defined a custom cpp interface and the required parameters used by this custom interface (as typedef or struct or class or another plugin or ...), the plugin template must be used to define a Factory Interface implemented in any plugin and used to create a new Plugin Specific Interface.

plugin.detail.001.png

Custom Interface and Parameters example

class CustomInterface
{
public:
CustomInterface(){};
virtual int getValue() = 0;
};
struct CustomParameters {
int initialValue;
int maxValue;
};

Definition of the Custom Factory Interface

Detailed Example

Overview

plugin.example.detail.001.png

Step 1: Definition of a generic interface.

File (genericInterface.hpp)

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <plugin/plugin.hpp>
#include <string>
/* Generic interface
*
* providing two virtual functions:
* doDomething
* doSomethingElse
*
* These two API will be implemented inside the plugins.
*
* NOTE:
* A possible standard implementation may be included here
* or in the genericinterface.cpp file. */
class GenericInterface
{
public:
GenericInterface(){};
virtual void doSomething() = 0;
virtual void doSomethingElse() = 0;
};
/* Generic Params
*
* Is the definition of all the parameters used to create the Generic Interface.
* To simplify this example (considering that no parameters are required)
* a simple std::string is used. */
typedef std::string GenericParams;
/*
* Declare plugin interface, after that new interface instances can be created with:
* OpenAB::PluginManager::getInstance().getPluginInstance<GenericInterface>("PluginName", <params>);
*/
DECLARE_PLUGIN_INTERFACE(, GenericInterface, GenericParams);

File (genericInterface.cpp)

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "genericInterface.hpp"
/* Made GenericInterface visible to OpenAB */
EXPORT_PLUGIN_INTERFACE(, GenericInterface, GenericParams)

Step 2: Plugin implementation.

Definition of all the Plugins that implement the required interface;

File (plugin1.cpp)

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <iostream>
#include "genericInterface.hpp"
/* Plugin1 class
* This class implement/extend the GenericInterface
* defined in "genericinterface.hpp". */
class Plugin1 : public GenericInterface
{
public:
void doSomething()
{
std::cout << "I'm doing something on Plugin1" << std::endl;
}
void doSomethingElse()
{
std::cout << "I'm doing something else on Plugin1" << std::endl;
}
};
/* The Factory specialization for this plugin
* is the base of the Plugin usage.
* It must provide 3 initialization steps. */
class Plugin1Factory : GenericFactory
{
public:
/* Step1: Definition of the Plugin Name in the constructor */
Plugin1Factory() : GenericFactory::Factory("Plugin1"){};
~Plugin1Factory(){}
/* Step2: newIstance routine where eventually
* the chosen parameters can be used*/
GenericInterface * newIstance(const GenericParams & params)
{
return new Plugin1();
};
};
/* Step3: adding the factory "Plugin1"
* trasparently to the (GenericFactory) Factories*/
REGISTER_PLUGIN_FACTORY(Plugin1Factory)

File (plugin2.cpp)

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <iostream>
#include "genericInterface.hpp"
class Plugin2 : public GenericInterface
{
public:
void doSomething()
{
std::cout << "I'm doing something on Plugin2" << std::endl;
}
void doSomethingElse()
{
std::cout << "I'm doing something else on Plugin2" << std::endl;
}
};
class Plugin2Factory : GenericFactory
{
public:
Plugin2Factory() : GenericFactory::Factory("Plugin2") {};
~Plugin2Factory(){}
GenericInterface * newIstance(const GenericParams & params)
{
return new Plugin2();
};
};
REGISTER_PLUGIN_FACTORY(Plugin2Factory)

Step 3: Usage inside the main code

Use the interface, referencing the plugins simply by name

Note
The main program does not have any knowledge of the plugin code except the name. This mechanism allow to add or remove plugins without modifying/rebuild the main code. The name of the plugin used as simple txt name can be an external input or be stored in a config file.

File (main.cpp)

/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
# Static Library Example:
# - Quick build from this folder:
g++ *.cpp -I../../../src/ ../../../src/logging/Log.cpp -o staticExample.out
# - Reference build (using the proper pkg-config):
g++ *.cpp `pkg-config OpenAB_plugin --libs --cflags` -o staticExample.out
# Shared Library Example:
# - Step1: Build all the plugins in a single shared library "libPlugin.so"
g++ plugin*.cpp `pkg-config OpenAB_plugin --libs --cflags` -shared -fPIC -o libPlugin.so
# - Step2: Build the executable enabling the shared library loading code "EXAMPLE_SHARED"
g++ main.cpp genericInterface.cpp \
`pkg-config OpenAB_plugin --libs --cflags` \
-DEXAMPLE_SHARED \
-o sharedExample.out
*/
#include <dlfcn.h>
#include <iostream>
#include "genericInterface.hpp"
#include <OpenAB.hpp>
int main(int argc, char* argv[])
{
#ifdef EXAMPLE_SHARED
OpenAB_Log::Log::OutLevel() = OpenAB_Log::Log::Debug;
//Scan directory to find plugins
#endif
/* The parameters required by the new instance must be defined here */
GenericParams p;
//Ask PluginManager to create new instance of plugin
GenericInterface * i1 = OpenAB::PluginManager::getInstance().getPluginInstance<GenericInterface>("Plugin1", p);
/* The Generic Interface, through the "Plugin1" can now be used */
i1->doSomething();
i1->doSomethingElse();
//Inform PluginManager that you are no longer using plugin instance
GenericInterface * i2 = OpenAB::PluginManager::getInstance().getPluginInstance<GenericInterface>("Plugin2", p);
i2->doSomething();
i2->doSomethingElse();
}