This example shows how to use modules (plugins) within your program and how to write such modules (plugins) with Vala.

The first thing needed is a common interface that will describe the interface between the main program and other modules / plugins.

Interface (plugin-interface.vala):

public interface TestPlugin : Object {
    public abstract void hello ();
}

This should be put into its own file that is then shared between the main program and plugins.

Main program (main.vala):

public class PluginRegistrar<T> : Object {

    public string path { get; private set; }

    private Type type;
    private Module module;

    private delegate Type RegisterPluginFunction (Module module);

    public PluginRegistrar (string name) {
        assert (Module.supported ());
        this.path = Module.build_path (Environment.get_variable ("PWD"), name);
    }

    public bool load () {
        stdout.printf ("Loading plugin with path: '%s'\n", path);

        module = Module.open (path, ModuleFlags.BIND_LAZY);
        if (module == null) {
            return false;
        }

        stdout.printf ("Loaded module: '%s'\n", module.name ());

        void* function;
        module.symbol ("register_plugin", out function);
        unowned RegisterPluginFunction register_plugin = (RegisterPluginFunction) function;

        type = register_plugin (module);
        stdout.printf ("Plugin type: %s\n\n", type.name ());
        return true;
    }

    public T new_object () {
        return Object.new (type);
    }
}

void main () {
    var registrar = new PluginRegistrar<TestPlugin> ("plugin");
    registrar.load ();

    var plugin = registrar.new_object ();
    plugin.hello ();
}

PluginRegistrar is a tool class that wraps registering, loading and creating new instances of TestPlugin class which are implemented in other classes contained in other modules.

Compiling:

$ valac --pkg gmodule-2.0 main.vala plugin-interface.vala -o main

A module must provide its own implementation of TestPlugin and a register_plugin method which is used to register the class in the main program.

Example of a plugin (plugin.vala):

class MyPlugin : Object, TestPlugin {
    public void hello () {
        stdout.printf ("Hello world!\n");
    }
}

public Type register_plugin (Module module) {
    // types are registered automatically
    return typeof (MyPlugin);
}

Compiling:

$ valac --pkg gmodule-2.0 -C plugin.vala plugin-interface.vala
$ gcc -shared -fPIC $(pkg-config --cflags --libs glib-2.0 gmodule-2.0) -o libplugin.so plugin.c

Real World Example(s)

A real world Vala application that uses this code as the base for its plugin loading is Rygel.


Vala/Examples

Projects/Vala/TypeModules (last edited 2013-11-22 16:48:32 by WilliamJonMcCann)