Generic plugin framework in C++.
- Generic plugin framework
- Arbitrary abstract base classes can be used as plugin interface
- Customizable with custom plugin factories (see examples)
- Works on linux, mac, windows and emscripten
All plugins are derived from a base class, in the first example MyPluginBase
.
All concrete plugins are derived from MyPluginBase
and implement the pure virtual function (in this example it is only the do_something()
function).
Furthermore, for this example, we assume that all concrete plugins have an empty constructor.
(see example 2 for a more complex example)
my_plugin_base.hpp
:
class MyPluginBase
{
public:
virtual ~MyPluginBase() = default;
virtual void do_something() = 0;
};
my_plugin_a.cpp
:
#include <my_plugin_base.hpp>
#include <xplugin/xfactory.hpp>
class MyPluginA : public MyPluginBase
{
public:
virtual ~MyPluginA() = default;
override void do_something() override
{
std::cout << "MyPluginA::do_something()" << std::endl;
}
}
using factory_type = xp::xfactory<MyPluginA, MyPluginBase>;
XPLUGIN_CREATE_XPLUGIN_FACTORY(factory_type);
my_plugin_b.cpp
:
#include <my_plugin_base.hpp>
#include <xplugin/xfactory.hpp>
class MyPluginB : public MyPluginBase
{
public:
virtual ~MyPluginB() = default;
override void do_something() override
{
std::cout << "MyPluginB::do_something()" << std::endl;
}
}
using factory_type = xp::xfactory<MyPluginB, MyPluginBase>;
XPLUGIN_CREATE_XPLUGIN_FACTORY(factory_type);
main.cpp
:
#include <my_plugin_base.hpp>
#include <xplugin/xplugin_registry.hpp>
#include <xplugin/xfactory.hpp>
#include <iostream> // just for the example
using factory_base_type = xp::xfactory_base<MyPluginBase>;
using plugin_registry_type = xp::xplugin_registry<factory_base_type>;
int main(int argc, char** argv)
{
if(argc != 2){
std::cout << "usage: " << argv[0] << " <plugin_directory>" << std::endl;
return 1;
}
std::string plugin_directory = argv[1];
plugin_registry_type registry(plugin_directory);
for (auto [name, factory] : registry){
std::cout << name << std::endl;
auto plugin = factory->create();
plugin->do_something();
}
}
We again define a plugin interface MyOtherPluginBase
and a concrete plugin implementations MyOtherPluginA
and MyOtherPluginB
.
The difference to the first example is that the concrete plugins have a constructor with arguments.
But both plugins have the same constructor signature.
my_other_plugin_base.hpp
:
class MyOtherPluginBase
{
public:
virtual ~MyOtherPluginBase() = default;
virtual void do_something() = 0;
};
my_other_plugin_a.cpp
:
#include <my_plugin_base.hpp>
#include <xplugin/xfactory.hpp>
class MyOtherPluginA : public MyPluginBase
{
public:
MyOtherPluginA(int some_data, const std::string & some_other_data)
: m_some_data(some_data)
, m_some_other_data(some_other_data)
{}
virtual ~MyOtherPluginA() = default;
override void do_something() override
{
std::cout << "MyOtherPluginA::do_something()" << std::endl;
std::cout << "some_data: " << m_some_data << std::endl;
std::cout << "some_other_data: " << m_some_other_data << std::endl;
}
private:
int m_some_data;
std::string m_some_other_data;
}
using factory_type = xp::xfactory<MyOtherPluginA, MyPluginBase, int, const std::string &>;
XPLUGIN_CREATE_XPLUGIN_FACTORY(factory_type);
my_other_plugin_b.cpp
:
#include <my_plugin_base.hpp>
#include <xplugin/xfactory.hpp>
class MyOtherPluginB : public MyPluginBase
{
public:
MyOtherPluginB(int some_data, const std::string & some_other_data)
: m_some_data(some_data)
, m_some_other_data(some_other_data)
{}
virtual ~MyOtherPluginB() = default;
override void do_something() override
{
std::cout << "MyOtherPluginB::do_something()" << std::endl;
std::cout << "some_data: " << m_some_data << std::endl;
std::cout << "some_other_data: " << m_some_other_data << std::endl;
}
private:
int m_some_data;
std::string m_some_other_data;
}
using factory_type = xp::xfactory<MyOtherPluginB, MyPluginBase, int, const std::string &>;
XPLUGIN_CREATE_XPLUGIN_FACTORY(factory_type);
main.cpp
:
#include <my_plugin_base.hpp>
#include <xplugin/xplugin_registry.hpp>
#include <xplugin/xfactory.hpp>
#include <iostream> // just for the example
using factory_base_type = xp::xfactory_base<MyOtherPluginBase, int, const std::string &>;
using plugin_registry_type = xp::xplugin_registry<factory_base_type>;
int main(int argc, char** argv)
{
if(argc != 2){
std::cout << "usage: " << argv[0] << " <plugin_directory>" << std::endl;
return 1;
}
std::string plugin_directory = argv[1];
plugin_registry_type registry(plugin_directory);
int some_data = 42;
std::string some_other_data = "Hello World";
for (auto [name, factory] : registry){
std::cout << name << std::endl;
auto plugin = factory->create(some_data, some_other_data);
plugin->do_something();
}
}