Have you ever wondered how to develop plug-ins for multiple platforms like Windows and Linux with the same code? Then, you should take a closer look at the Simple Plug-in Layer (SPL) Library!
About this library
The SPL (Simple Plug-in Layer) library is an open source SDK (LGPL license) for plug-in development. With SPL, you can extend any application written in C/C++ to use your own plug-ins, the SPL will do all the managing, loading and unloading stuff for you. Additionally, the whole framework is fully multi-platform capable, so you don't have to develop multiple versions of the same plug-in for platforms provided by SPL.
This library was developed by Andreas Loeffler and René Stuhr. Please visit this site for updates and more useful stuff on SPL.
- 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 plug-in development.
- Variable plug-in 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.
- Can be built as static/shared library or DLL (only Win32).
- Various examples for all the platforms explaining the development step by step.
- Source code written in uniform style.
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 that you can use optionally to speed up your plug-in development.
A plug-in consists of four simple C-functions, all of which except one can be implemented as "default-functions" without any code behind it, using SPL's macros:
Run (cannot be used as default-function)
What does a "default-function" mean? A default-function is a simple function without any code in it. Since SPL requires these four functions in any case, you can 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:
So, why doesn't the
Run function have such a macro? Hmmm, well, if we 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:
These two macros provide some Windows-specific code which is not used by other platforms like 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 platform, 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
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:
This macro derives a class from
slcPluginInfo, which is responsible for holding plug-in information like name, version, build number, vendor etc., and it 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 make it working, a simple example on how to implement a plug-in without the macros is included in the SPL package.
Since our header file is now complete, let's step into our .cpp file:
SPL_PLUGIN_API bool SPL_INIT_NAME_CODE(
slcPluginArgs* a_pPluginArgs )
printf( "HelloWorld: Hi there! Here " +
"we could initialize something!\n" );
SPL_PLUGIN_API bool SPL_RUN_NAME_CODE(
slcPluginArgs* a_pPluginArgs )
printf( "HelloWorld: Hi, this is the plugin's " +
"run function!\n" );
SPL_PLUGIN_API bool SPL_SHUTDOWN_NAME_CODE(
slcPluginArgs* a_pPluginArgs )
printf( "HelloWorld: Bye, bye world, this " +
"is the shutdown function.\n" );
Looks very simple, doesn't it? I have not used any "default-function" macros (except for the
GetInfo function) here, since I wanted to present how you can use all the functions (again, except
GetInfo) on your own.
"Hm, okay, sounds good, but when are these functions called?" I hear you whisper ..that's a good question!
The reason why almost nobody would implement their own version of
GetInfo is that this function basically does nothing other than returning a pointer to the plug-in information structure that we filled in the header by using the macro
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,
Shutdown is either called manually by the user if his program ends or it's done by the 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 also included. Builds for Microsoft .NET 2003, Microsoft Visual Studio 6.0 and Linux (GCC) are also included.
Screenshot of the MFC example application
This screenshot shows an example application which is included in the SDK:
On the left side: our MFC example application showing all the loaded plug-ins and using the SPL library as DLL build. In the left list view, you see all the loaded plug-ins with the first plug-in selected. In the small window on the right, you see the information of the selected plug-in. You can modify a given text 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 the loaded plug-in processes.
Please visit here to get more information on this library.