How To Define a New Plug-in Factory

Overview

SEAL plug-in system allows any C++ objects to be created through a factory. The implementation of the object can be loaded on demand at run-time; the factory client does not need to worry about this. Thus the physical composition of the application (distribution of class implemenations into libraries and the program itself) is decoupled from the factory usage. On the other hand, the application is always fully aware of all plug-ins available, whether or not they are currently loaded. Furthermore, any package, including those that are modules themselves, can define new plug-in factories.

This guide explains how to define your own plug-in factory or category. Follow these steps:

Let's assume you wish to define a SampleFactory, a plug-in factory creating objects of type SampleObject. This example follows the SEAL coding conventions, please refer to your own project guidelines for more details.

Define object you create

You need to define the type of object you create. It can be any valid C++ type. Normally you define your own class with an abstract interface that makes sense for your category. You can even get away without any type; plug-ins of that type are called capabilities. In this case, we assume there is a type SomeObject, which has at least a virtual destructor, possibly some virtual functions, and whose subclasses must be created with two arguments, an int and a double.

Define the factory class

Next, you need to define the factory itself. It would normally look something like this:

#ifndef SOME_PACKAGE_SOME_FACTORY_INFO_H
# define SOME_PACKAGE_SOME_FACTORY_INFO_H
//<<<<<< INCLUDES                                   >>>>>>

# include "SomePackage/SomeObject.h"
# include "PluginManager/PluginFactory.h"

//<<<<<< PUBLIC DEFINES                             >>>>>>
//<<<<<< PUBLIC CONSTANTS                           >>>>>>
//<<<<<< PUBLIC TYPES                               >>>>>>
//<<<<<< PUBLIC VARIABLES                           >>>>>>
//<<<<<< PUBLIC FUNCTIONS                           >>>>>>
//<<<<<< CLASS DECLARATIONS                         >>>>>>

/// Plug-in factory for objects of type #SomeObject.
class SomeFactory : public seal::PluginFactory<SomeObject *(int, double)>
{
public:
    static SomeFactory *get (void);

private:
    SomeFactory (void);
    static SomeFactory s_instance;
};

//<<<<<< INLINE PUBLIC FUNCTIONS                    >>>>>>
//<<<<<< INLINE MEMBER FUNCTIONS                    >>>>>>

#endif // SOME_PACKAGE_SOME_FACTORY_INFO_H

The implementation looks like this:

//<<<<<< INCLUDES                                   >>>>>>

#include "SomePackage/SomeFactory.h"

//<<<<<< PRIVATE DEFINES                            >>>>>>
//<<<<<< PRIVATE CONSTANTS                          >>>>>>
//<<<<<< PRIVATE TYPES                              >>>>>>
//<<<<<< PRIVATE VARIABLE DEFINITIONS               >>>>>>
//<<<<<< PUBLIC VARIABLE DEFINITIONS                >>>>>>
//<<<<<< CLASS STRUCTURE INITIALIZATION             >>>>>>

SomeFactory SomeFactory::s_instance;

//<<<<<< PRIVATE FUNCTION DEFINITIONS               >>>>>>
//<<<<<< PUBLIC FUNCTION DEFINITIONS                >>>>>>
//<<<<<< MEMBER FUNCTION DEFINITIONS                >>>>>>

SomeFactory::SomeFactory (void)
    : seal::PluginFactory<SomeObject *(int, double)> ("Factory Label")
{}

SomeFactory *
SomeFactory::get (void)
{ return &s_instance; }

Migrating from SEAL 1.3.x plug-in manager

Given a plug-in type X for which you had a factory XFactory with constructor argument list (int, double), you:

  1. Delete your XInfo (PluginInfo derived) class completely
  2. Define your factory as shown above: class XFactory : public PluginFactory<X *(int, double)> { ... };
    (It used to be declared as: XFactory : PluginFactory<XInfo>.)

You automatically get create(int, double) etc methods in the base class, so if you had that stuff, delete it all in your XFactory. The only method the factory needs to have is static XFactory *get(void), which should return the address of a statically constructed object. Note that you must follow exactly the pattern shown above — do not make the static factory object local to the get() function or a pointer! The plug-in manager relies on it being a global object.

If you want to have a plug-in category that doesn't create anything, but loads other libraries for their side effects, derive your XFactory from PluginFactory<void>. You'll get void load(std::string name) instead of X *create (std::string name, ...) in the base class to load the side effects. You can use PluginCapabilities as an example.