3 min read

Plugins so easy, electrical outlets are jealous: Part 1

Topics:

No software product out there can fully offer all of the features that are required by an end user.  In order to mitigate this, most products now offer an interface through which a user can extend the functionality.  Our product suite is no different.  The tooling side of our product is based on Eclipse, which has legendary extendability.  You can also extend our runtime as well. When our runtime starts up, it searches the plugin path for compatible plugins to load.  This plugin path is set through a command line option, or by setting an environment variable.  Over my next couple of blog posts, I am going to walk through the process of creating a plugin for our runtime.

The first thing you should know when you are creating a Storyboard Engine is that the name of the plugin needs to contain the string "-plugin" in it.  Also, the plugin needs to be a shared object, so it needs to end with a ".so" on unix based systems and ".dll" on windows.

So lets start.  First, grab the Storyboard SDK and install it on your development system.  Now create a directory called "my-first-sbengine-plugin".  Straightforward so far, right?  Now in that directory create a makefile and put the following in it:

my-first-plugin.o:
$(CC) -shared -fPIC -c my-first-plugin.c \
-I /home/rdowdall/Documents/workspace/sbengine/linux-x86_64-sdl-obj/include/gre/sdk \
-I /home/rdowdall/Documents/workspace/sbengine/linux-x86_64-sdl-obj/include/gre/ \
-I /home/rdowdall/Documents/workspace/sbengine/linux-x86_64-sdl-obj/include/

libgre-myfirst-plugin.so: my-first-plugin.o
$(CC) -o libgre-myfirst-plugin.so -shared -fPIC my-first-plugin.o

all: libgre-myfirst-plugin.so

This will allow us to make our library.  Next create a my-first-plugin.c file and put the following in it:

/*
* my-first-plugin.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "managers.h"

#define MAJOR_VERSION 1
#define MINOR_VERSION 0
#define SERVICE_VERSION 0
#define BUILD_VERSION 0

static int
myfirst_init(gr_application_t *app, const char *args, void *pdata) {
/* Called when the plugin is starting up */
printf ("Hello, I am starting\n");
}

static void
myfirst_fini(gr_application_t *app, void *pdata) {
/* Called when the plugin is going away */
printf ("Goodbye I am stopping\n");
}

/* When sbengine is adding plugins to it's *
* list will look for this function, and invoke it. */
int
GRE_PLUGIN_CREATE_FUNC(gr_plugin_state_t *state) {
memset(state, 0, sizeof(*state));
SET_PLUGIN_VERSION(&state->version, MAJOR_VERSION, MINOR_VERSION, SERVICE_VERSION, BUILD_VERSION);
state->name = strdup("my-first-plugin");
state->plugin_data = NULL;
state->init = myfirst_init;
state->fini = myfirst_fini;
return 0;
}

When the Storyboard Engine is looking at plugins to load, it looks for the GRE_PLUGIN_CREATE_FUNC function and calls it with a plugin state variable. You fill in this variable with a name, version, any global data that you want to have associated with the plugin, and the functions used to initialize and uninitialize your plugin. It then adds the plugins to it's list of plugins to invoke. When it is time to invoke this plugin it will call myfirst_init, which will in turn print out "Hello, I am starting". When the engine terminates, it will call myfirst_fini, which will print "Goodbye I am stopping". You should be able to type make in your my-first-plugin directory and have it build you a libgre-myfirst-plugin.so. Then you can put this in the plugins directory of your Storyboard Engine, export the environment variable GRE_PLUGINS to point to that plugins directory, and run the engine. You should see the printouts when the library loads, and unloads.

So if your project requires you to write a plugin that prints out messages from a plugin only when it loads and unloads, then great, you are done. Go in and tell your boss how awesome you are. If you need to write a plugin that needs to actually do something more involved, well, you are going to have to read my next blog post. In that one, I'll show you how to listen for events, and then do stuff when those events happen. I'm not going to lie to you, the do stuff part may still be printouts, but they will be meaningful printouts.

Rodney