Plugins

Ordinarily, when we think of plugins in software, we think of shared libraries being opened with dlopen() at runtime. To avoid the requirement for shared libraries and dlopen(), MACSio uses a simpler link-time approach to handling plugins called static plugins. In this case, the plugin’s available to MACSio are determined when MACSio’s main() is linked. Whatever plugins are included on the link line are then available to MACSio.

MACSio exploits a feature in C++ which permits initialization of static variables via non-constant expressions In fact, the only reason MACSio requires a C++ compiler is for the final link to support this feature.

All symbols in a plugin source file are defined with static scope. Every plugin defines an int register_this_plugin(void) function and initializes a static dummy integer to the result of a call to register_this_plugin() like so…

static int register_this_plugin(void)
{
  MACSIO_IFACE_Handle_t iface;

  strcpy(iface.name, iface_name);
  strcpy(iface.ext, iface_ext);

  if (!MACSIO_IFACE_Register(&iface))
      MACSIO_LOG_MSG(Die, ("Failed to register interface \"%s\"", iface.name));
}
static int dummy = register_this_plugin();

In the above code example, the call to MACSIO_IFACE_Register() calls a method in MACSio’s main which does the work of adding the plugin’s interface specification (MACSIO_IFACE_Handle_t) to a statically defined table of plugins. The plugin’s id is its location in that table.

Each plugin is defined by a file such as macsio_foo.c for a plugin named foo in the plugins directory. macsio_foo.c implements the MACSIO_IFACE interface for the foo plugin.

At the time the executable loads, the register_this_plugin() method is called. Note that this is called long before even main() is called. The call to MACSIO_IFACE_Register() from within register_this_plugin() winds up adding the plugin to MACSio’s global list of plugins. This happens for each plugin. The order in which they are added to MACSio doesn’t matter because plugins are identified by their (unique) names. If MACSio encounters a case where two different plugins have the same name, then it will abort and inform the user of the problem. The remedy is to adjust the name of one of the two plugins. MACSio is able to call static methods defined within the plugin via function callback pointers registered with the interface.

group MACSIO_IFACE

Plugin Interface Specification.

Defines

MACSIO_IFACE_MAX_COUNT

Maximum number of plugins possible.

MACSIO_IFACE_MAX_NAME

Maximum length of any plugin’s name.

Typedefs

typedef void (*DumpFunc)(int argi, int argc, char **argv, json_object *main_obj, int dumpNum, double dumpTime)

Main mesh+field dump (write) function specification.

typedef void (*LoadFunc)(int argi, int argc, char **argv, char const *path, json_object *main_obj, json_object **data_read_obj)

Main mesh+field load (read) function specification.

typedef int (*ProcessArgsFunc)(int argi, int argc, char **argv)

Command-line argument processing function for plugin.

typedef int (*QueryFeaturesFunc)(void)

Function to query plugin’s features (not currently used)

typedef int (*IdentifyFileFunc)(char const *pathname)

Function to ask plugin if it recognizes a given file.

typedef struct MACSIO_IFACE_Handle_t MACSIO_IFACE_Handle_t

Plugin interface handle type.

Functions

int MACSIO_IFACE_Register(MACSIO_IFACE_Handle_t const *iface)

Register a plugin with MACSIO.

Parameters
  • iface: The interface specification for a new plugin

This function should be called from within a code-block which is executed as part of a static initiliztion of the plugin’s local, static variables like so…

static int register_this_plugin(void)
{
    MACSIO_IFACE_Handle_t iface;
    iface.name = "foobar";
    iface.ext = ".fb";
    .
    .
    .
    MACSIO_IFACE_Register(&iface);
    return 0;
}
static int dummy = register_this_plugin()

void MACSIO_IFACE_GetIds(int *cnt, int **ids)

Return all registered plugin ids.

Parameters
  • cnt: the number of registered plugins available

  • ids: the list of ids of the registered plugins

void MACSIO_IFACE_GetIdsMatchingFileExtension(char const *ext, int *cnt, int **ids)

Return plugin that recognize files with a given extension.

Parameters
  • ext: the file extension to query

  • cnt: the number of plugins that recognize the extension

  • ids: the list of ids of the matching plugins

int MACSIO_IFACE_GetId(char const *name)

return id of plugin given its name

Return

On error, returns -1. Otheriwse a non-negative valid plugin id.

char const *MACSIO_IFACE_GetName(int id)

Get name of plugin given its id.

Return

On error, returns (char*)0. Otheriwse a non-null name of valid plugin.

MACSIO_IFACE_Handle_t const *MACSIO_IFACE_GetByName(char const *name)

Get interface handle for a plugin given its name.

Return

On error, returns (MACSIO_IFACE_Handle_t*)0. Otherwise returns a valid plugin interface handle.

MACSIO_IFACE_Handle_t const *MACSIO_IFACE_GetById(int id)

Get interface handle for a plugin given its id.

Return

On error, returns (MACSIO_IFACE_Handle_t*)0. Otherwise returns a valid plugin interface handle.

Variables

char name[MACSIO_IFACE_MAX_NAME]

Name of this plugin

char ext[MACSIO_IFACE_MAX_NAME]

File extension of files associated with this plugin

int slotUsed

[Internal] indicate if this position in table is used

ProcessArgsFunc processArgsFunc

Plugin’s command-line argument processing callback

DumpFunc dumpFunc

Plugin’s main dump (write) function callback

LoadFunc loadFunc

Plugin’s main load (read) function callback

QueryFeaturesFunc queryFeaturesFunc

Plugin’s callback to query its feature set (not in use)

IdentifyFileFunc identifyFileFunc

Plugin’s callback to indicate if it thinks it owns a file

struct MACSIO_IFACE_Handle_t
#include <macsio_iface.h>

Plugin interface handle type.

Public Members

char name[MACSIO_IFACE_MAX_NAME]

Name of this plugin

char ext[MACSIO_IFACE_MAX_NAME]

File extension of files associated with this plugin

int slotUsed

[Internal] indicate if this position in table is used

ProcessArgsFunc processArgsFunc

Plugin’s command-line argument processing callback

DumpFunc dumpFunc

Plugin’s main dump (write) function callback

LoadFunc loadFunc

Plugin’s main load (read) function callback

QueryFeaturesFunc queryFeaturesFunc

Plugin’s callback to query its feature set (not in use)

IdentifyFileFunc identifyFileFunc

Plugin’s callback to indicate if it thinks it owns a file