Ikke's Blog

Post details: GModules are fun

May 18
GModules are fun

Glib's GModules are fun :-) These functions provide a braindead interface to modular (think "plug-in based") programming. I wrote some testing code today (read the API a year ago or so but never played with it), here's a short introduction.

When writing module based applications there are mainly 2 parts: the modules, and the application using them. So we'll have to write these 2 things.

Getting started with the module is the easiest part:

#include <glib.h>
#include <gmodule.h>

G_MODULE_EXPORT void m_helloworld() {
        g_print("Hello modular world!\n");
}

This code is pretty straight-forward. The only "strange" thing is G_MODULE_EXPORT, a platform-independent macro telling the compiler/linker to export the function.

Then comes the "client" application, a little more difficult. Comments inline:

#include <glib.h>
#include <gmodule.h>

/* A prototype of the function pointer we'll use */
/* void function(void) */
typedef void (*HelloWorldFunc) (void);

gint main(gint argc, gchar *argv[]) {
        /* We need:
         * - A handle to our module
         * - A pointer to the function we'll import
         * - Some helper strings */
        GModule *module = NULL;
        HelloWorldFunc hello = NULL;
        gchar *module_path = NULL, *curr = NULL;

        /* Check whether glib is compiled with module support */
        if(g_module_supported() == FALSE) {
                g_error("Modules not supported :(");
                return 1;
        }
        
        /* We need to figure out the path to our module. In our test case, this
         * is ".", so we want the current dir. */
        curr = g_get_current_dir();
        /* Create the path to the module. This function does quite a lot of
         * of things, check the GModule API. */
        module_path = g_module_build_path((const gchar *) curr, "module");
        /* Don't we love debugging? */
        g_debug("Module path: %s", module_path);

        /* Finally we're able to open the module. We want lazy symbol resolving.
         * This means we only want a symbol to be resolved if we request it.
         * Once more, see the API for more information. */
        module = g_module_open(module_path, G_MODULE_BIND_LAZY);

        /* Get rid of those helper strings */
        g_free(module_path);
        g_free(curr);

        /* Check whether the module was loaded successfully */
        if(module == NULL) {
                g_error("Unable to load module");
                return 1;
        }

        /* Load the symbol and assign it to our function pointer. 
         * Check for errors */
        if(g_module_symbol(module, "m_helloworld", (gpointer *) &hello) == FALSE) {
                g_error("Unable to get function reference: %s", g_module_error());
                return 1;
        }

        /* Now we can call our funtion.
         * As you can see, we can call it as if it's a normal function.
         * Don't we love function pointers? */
        hello();

        /* We're nice citizens and close all references when we leave */
        if(g_module_close(module) == FALSE) {
                g_error("Unable to close module: %s", g_module_error());
                return 1;
        }

        return 0;
}

(this looks like a lot of code (well...) but if you strip all comments and debugging stuff/checks, you'll only have 10 lines or so)

Should be quite easy to understand too.

Now it's compile time. Of course, in a real-world situation, we'd use autotools to compile our libraries, we'd have a libtoolized library etc etc etc. Here we'll do it in the quick-and-dirty way:

# gcc -o libmodule.so -shared `pkg-config --libs --cflags glib-2.0 gmodule-2.0` module.c
# gcc -o main `pkg-config --libs --cflags glib-2.0 gmodule-2.0` main.c
# ls
libmodule.so  main  main.c  module.c
# ./main
** (process:26533): DEBUG: Module path: /home/foo/bar/libmodule.so
Hello modular world!

Loading all these symbols by hand is a boring task, so most of the time you'll create some API using vtables to make your life easier. More on this later (got to study now ;-) :|)

Comments:

Comment from: mutulica [Visitor]
great tutorial.i was looking for sommething straight forward and yours is just right.
took me some time to google it thogh.
thanx.
PermalinkPermalink 06/12/05 @ 22:31
Comment from: molivier [Visitor]
great tutorial.i was looking for this too !

Thanks !
PermalinkPermalink 07/08/05 @ 23:59
Comment from: molivier [Visitor]
Do you know how to call an external function ( from the main application ) from a module ?

Regards,
PermalinkPermalink 07/09/05 @ 01:34

Leave a comment:

Your email address will not be displayed on this site.
Your URL will be displayed.

Allowed XHTML tags: <p, ul, ol, li, dl, dt, dd, address, blockquote, ins, del, span, bdo, br, em, strong, dfn, code, samp, kdb, var, cite, abbr, acronym, q, sub, sup, tt, i, b, big, small>
(Line breaks become <br />)
(Set cookies for name, email and url)
(Allow users to contact you through a message form (your email will NOT be displayed.))

Categories

Who's Online?

  • Guest Users: 456

Misc

XML Feeds

What is RSS?