Archives for: May 2005, 18

05/18/05

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 ;-) :|)

Permalink . Ikke . 04:02:11 pm . 600 Words . Technology, Linux, Desktop, Coding Corner . . 989 views . 3 comments
Portage on Windows

Maybe one day we'll be able to get lots of *nix software running under Windows using Gentoo's Portage. Read this.

Permalink . Ikke . 01:34:49 pm . 37 Words . Life . . 272 views . 7 comments
cannot map sys bios

Yesterday, I placed gnome and all dependencies in my packages.keywords (with the ~x86 keyword of course) so I could install gnome 2.10. Worked fine, but when I booted a few hours later, my X-server couldn't start. Normally there should be no correlation between these two facts, but it's the only thing that changed between a working and a non-workig X. This is the error I recieve:
(EE) RADEON(0): Cannot map SYS BIOS

Ikke was here yesterday night, but he couldn't fix it too. He tried with vesa, some modules and xorg.conf from a working ubuntu liveCD, but all without any effect. We also recompiled xorg, but this also wasn't the solution.

If you know any, please let me know! If I find it, I'll sure post the solution here.

You can find a more detailed error log here and my xorg.conf file here. Yesterday I worked graphical till 18 hours (I don't know when I restarted my X then), but it didn't work after I booted up at 0.30 am this morning. The packages I emerged yesterday can be found in my genlop log.

Permalink . Peter . 09:19:55 . 184 Words . My Gentoo . Email . No views