Sunday, November 2, 2014

Creating Basic C++ Plugins (Part 3 of 3)

Part 1 introduced the basics of the plugin system. Part 2 created a class of shared libraries, then showed a sample program to load the plugins and execute them. Finally, here in part 3, we'll make a custom plugin and run it through our program from the last example. This final set of code is the simplest, check it out.


Creating Basic C++ Plugins (Part 2 of 3)

In the first part of this tutorial, we covered the basic setup of what it takes to start on a plugin system in C++. This meant getting used to function calling conventions, why they matter, and how they apply to executables vs libraries. Part 1 then went on to create the basic API that will be used throughout the remainder of the tutorial. Part 2 will now go over some skeleton code to contain a handle to a shared library (using RAII), then walk through a method to load and verify a library at runtime.

*Make sure you have SDL2 installed before continuing.

Creating Basic C++ Plugins (Part 1 of 3)

One of the things that I plan on introducing into LightSky is a basic plugin system. If you want to insert a custom renderer, audio library, file loader, or more into the game engine, chances are that you would rather not recompile the entire library in order to allow it. In this basic tutorial, I'll cover the basics of making a shared library loader that uses RAII in order to close resources automatically. This tutorial will also use G++ (through MinGW) and SDL in order to load/unload shared libraries on different platforms such as Windows, Linux, and OSX. Now to get started, I'll assume an advanced level of C++ knowledge. You should be familiar with the difference between a static and shared library, pointer arithmetic, and function calling conventions.

The program in this tutorial is split into 3 parts; the first part is as follows:

  1. Design an abstract base class which will be used to create client plugins.
  2. Add OS-specific bindings to the API in order to improve cross-platform functionality.
  3. Create a private library-loader class which will handle all resource loading/unloading using RAII.


Part 2 dives into the runtime environment:
  1. Start main() with the input parameters argc and argv.
  2. For each input string in argc:
    1. Verify the parameter is a valid path to a shared libary,
    2. Attempt to load a shared library using the input path name.
    3. Run the plugin.

For part 3:
  1. Create a plugin class which inherits from a pre-defined API base type.
  2. Create a factory method to instantiate the derived class from within the shared library.
  3. Create a deletion method which will destroy any instantiated class methods using the shared library.
  4. Compile the library as either a DLL or SO file.
  5. Run the file using the program created in part 1.
Simple, right? Let's get started.