Introduction
Have you ever wondered how to develop plugins for multiple platforms such as Windows AND Linux with the same code? Then you should take a closer look at the Simple Plugin Layer (SPL) Library!
About This library
The SPL (Simple Plugin Layer) library is an open source SDK (LGPL license) for plugin development. With SPL, you can extend every application written in C/C++ to use your own plugins; SPL will do all the managing, loading, and unloading of stuff for you. Additionally, the whole framework is fully multi-platform capable, so you don’t have to develop multiple versions of the same plugin for platforms provided by SPL.
This library was developed by Andreas Loeffler and Reni Stuhr. Please visit http://www.unitedbytes.de/go.php?site=spl for updates and more useful stuff regarding SPL.
Features
- Open Source, uses LGPL license
- Free, costs absolutely nothing, even for commercial use
- Platform-independent architecture
- Implementations for Linux and Win32 available; more platforms coming soon …
- Full Doxygen-/Javadoc-compatible documentation
- Optional macros for fast and easy plugin development
- Variable plugin arguments for extensible APIs
- Thread safety for complex applications
- Uses STL library for stable and portable containers
- Object-oriented design, easy to extend
- Customizable to 32- or 64-bit systems
- Completely written in C++; no other dependencies except STL needed
- Buildable as static/shared library or DLL (only Win32)
- Various examples for all platforms explaining the development step by step
- Source code written in a uniform style
Overview
SPL is divided in two parts: Functions/classes for applications that want to use plug-ins, and the plug-in development side. The plug-in development side offers macros you can use optionally to speed up your plug-in development.
A plug-in consists of four simple C functions, which all except one can be implemented as “default-functions” without any code behind it, using SPL’s macros:
GetInfo
Initialize
Run (cannot be used as default-function)
Shutdown
What does “default function” mean, you might ask now? A default function is a simple function without any code in it. Because SPL requires these four functions in any case, you could use SPL’s macros for implementing it. If you want to use one of these functions in a special way, just don’t use the function macro and implement that function for yourself.
For these three functions, SPL uses the following macros:
SPL_IMPLEMENT_PLUGIN_GETINFO();
SPL_IMPLEMENT_PLUGIN_INITIALIZE();
SPL_IMPLEMENT_PLUGIN_SHUTDOWN();
So, why doesn’t the Run function have such a macro? Hmmm, well, if we would have such a macro, the Run function would be implemented by default with no code, so the plug-in does nothing.
Note: If you want to use/compile your plug-in with Windows, you need two additional macros provided by SPL, they’re called SPL_DEFINE_PLUGIN_EXPORTS(); and SPL_DEFINE_PLUGIN_DLLMAIN();.
These two macros provide some Windows-specific code that is not used by other platforms such as Linux, for example. Don’t worry about it; you can put them safely into your plug-in. It does not matter if you want to compile/use your plug-in on Linux platforms; SPL does all the stuff internally for you, so you won’t have to change anything to compile AND use your plug-ins on different platforms!
A “Hello-World” Plug-in
Let’s start with a very simple “Hello-World” plug-in. This example is also included in the SPL package. Our goal is a simple plug-in that compiles/runs on Windows and Linux without doing any changes in the source code when “porting” it. Okay, actually you don’t have to “port” anything.
Have a look at the header file:
#if SPL_PLATFORM == SPL_PLATFORM_WIN32 #include <windows.h> #endif SPL_DEFINE_PLUGIN_EXPORTS(); SPL_DEFINE_PLUGIN_INFO( 1, /// The build number. 1, /// The major version /// (e.g. 1.xx). 0, /// The minor version /// (e.g. 0.10). true, /// Does this plugin show its /// arguments to the public? "plHelloWorld", /// The plugin's name. "United Bytes", /// The plugin's vendor. "Hello world, our first plugin!", /// The plugin's general /// description. "Simple test plugin! :-)", /// The plugin's additional /// description. "http://www.unitedbytes.de", /// The plugin vendor's /// home page. "[email protected]", /// The plugin vendor's /// e-mail address. "ConsoleExampleAPI" ); /// The plugin's UUID.
That’s really all you need in your header file. We already discussed the SPL_DEFINE_PLUGIN_EXPORTS(); macro, so let’s go to the macro.
SPL_DEFINE_PLUGIN_INFO();
This macro derives a class from slcPluginInfo, which is responsible to hold the plug-in’s information like name, version, build number, vendor etc., and creates a global instance called g_pluginInfo. This global object is required for all default function macros of SPL.
Note for hardcore-coders: You don’t need any of SPL’s macros to get it working. A simple example on how to implement a plug-in without all macros is included in the SPL package.
Because our header file is now complete, let’s step into our .cpp file!
#include "plHelloWorld.h" SPL_DEFINE_PLUGIN_DLLMAIN(); SPL_IMPLEMENT_PLUGIN_GETINFO(); SPL_PLUGIN_API bool SPL_INIT_NAME_CODE( slcPluginArgs* a_pPluginArgs ) { printf( "HelloWorld: Hi there! Here we could initialize something!\n" ); return true; } SPL_PLUGIN_API bool SPL_RUN_NAME_CODE( slcPluginArgs* a_pPluginArgs ) { printf( "HelloWorld: Hi, this is the plugin's run function!\n" ); return true; } SPL_PLUGIN_API bool SPL_SHUTDOWN_NAME_CODE( slcPluginArgs* a_pPluginArgs ) { printf( "HelloWorld: Bye, bye world, this is the shutdown function.\n" ); return true; }
Looks very simple, doesn’t it? You may notice that I don’t use any “default function” macros (except for the GetInfo function) in here because I want to present how you can use all functions (again, except GetInfo) on your own.
“Hm, okay, sounds good, but when are all these functions called?” I hear you whisper … that’s a good question!
The reason why almost nobody would implement his own version of GetInfo is that this function basically does nothing other than return a pointer to the plug-in information structure we filled in the header by using the macro SPL_DEFINE_PLUGIN_INFO().
The Initialize function is called when a plug-in is successfully loaded, GetInfo is called manually from the user’s code if he wants to get more information about the plug-in, Run contains the actual plug-in code, and Shutdown is either called manually by the user if his program ends or it’s done by SPL’s destructor to give all plug-ins a chance to clean themselves up.
Various examples using SPL are included in the SDK, a Doxygen-generated documentation for all parameters and functions is included, too. Builds for Microsoft .NET 2003, Microsoft Visual Studio 6.0 and Linux (GCC) are included.
Screenshot of the MFC Example Application
This screenshot shows an example application that is included in the SDK:
On the left side: Our MFC example application shows all loaded plug-ins and using the SPL library as DLL build. In the left list view, you see all loaded plug-ins; the first plug-in is selected. In the small window on the right, you see information about the selected plug-in. You can modify a given text by using the selected plug-in(s).
On the right side: The red line marks the example application itself. Beneath the line, you can see all loaded plugin processes.
Resources
Please visit here for more information about this library, and the official forum located at http://www.unitedbytes.de/go.php?site=spl and http://forum.unitedbytes.de
Download
Download the Simple Plugin Layer Library v0.4 here.