C:SPL tutorials

From GPWiki
Jump to: navigation, search

Introduction

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 every application written in C/C++ to use your own plug-ins, 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 here 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 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 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 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 4 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. Since SPL requires these 4 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 you want, just don't use the function-macro and implement that function for yourself.

For these 3 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(); SPL_DEFINE_PLUGIN_DLLMAIN();

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 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:

  1. if SPL_PLATFORM == SPL_PLATFORM_WIN32
#include <windows.h>
  1. 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 homepage.
       "info@unitedbytes.de",       ///< The plugin vendor's email 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.

Since our header file is now complete, let's step into our .cpp file!

  1. 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, since 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 an own version of GetInfo is that this function basically does nothing else than returning 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, 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.