]> git.draconx.ca Git - upkg.git/commitdiff
Implement dynamic loading of modules.
authorNick Bowler <nbowler@draconx.ca>
Tue, 9 Jun 2009 22:49:37 +0000 (18:49 -0400)
committerNick Bowler <nbowler@draconx.ca>
Tue, 9 Jun 2009 23:13:38 +0000 (19:13 -0400)
.gitignore
src/Makefile.am
src/engine/Makefile.inc [new file with mode: 0644]
src/engine/engine.c [new file with mode: 0644]
src/engine/music.c [moved from src/music.c with 75% similarity]
src/engine/music.h [new file with mode: 0644]
src/module.c
src/module.h
src/music.h [deleted file]
src/upkg.c

index 527fdf72e00da21b0f2e4bedd608c4bd63f9f500..03e7f99ae6a01a86f9a9056e33f12626589b8c05 100644 (file)
@@ -5,6 +5,7 @@ Makefile
 Makefile.in
 .libs
 .deps
+.dirstamp
 config.*
 aclocal.m4
 autom4te.cache
@@ -15,6 +16,7 @@ ltmain.sh
 install-sh
 depcomp
 missing
+mkinstalldirs
 stamp-h1
 compile
 upkg
index 8b3567639e97e72baff8e2518a6b6b9aab606201..436203e3f6ecf0d04f914d6a7f49ea987f2dd823 100644 (file)
@@ -6,10 +6,12 @@ noinst_HEADERS = pack.h
 
 if BUILD_UPKG
 
+include engine/Makefile.inc
+
 bin_PROGRAMS  = upkg
-upkg_SOURCES  = upkg.c module.c exportable.c serializable.c music.c
+upkg_SOURCES  = upkg.c module.c exportable.c serializable.c
 upkg_CPPFLAGS = $(GLIB_CFLAGS) $(LTDLINCL)
-upkg_LDFLAGS  = $(GLIB_LIBS)
+upkg_LDFLAGS  = $(GLIB_LIBS) -export-dynamic
 upkg_LDADD    = libupkg.la $(LIBLTDL)
 
 endif
diff --git a/src/engine/Makefile.inc b/src/engine/Makefile.inc
new file mode 100644 (file)
index 0000000..62ad702
--- /dev/null
@@ -0,0 +1,7 @@
+noinst_HEADERS += engine/music.h
+
+lib_LTLIBRARIES   += engine.la
+engine_la_SOURCES  = engine/music.c engine/engine.c
+engine_la_CFLAGS   = $(GLIB_CFLAGS)
+engine_la_LDFLAGS  = $(GLIB_LIBS)
+engine_la_LDFLAGS += -module -avoid-version -export-symbols-regex _LTX_
diff --git a/src/engine/engine.c b/src/engine/engine.c
new file mode 100644 (file)
index 0000000..732a94a
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include <glib-object.h>
+
+#include "music.h"
+
+#define init engine_LTX_init
+
+int init(GTypeModule *m)
+{
+       music_register(m);
+       return 0;
+}
similarity index 75%
rename from src/music.c
rename to src/engine/music.c
index 4c64a7b670b4b324d040fb4d731069fda6bd76c8..0c0cdf81be1253155ac15e6cd79299ece2d97278 100644 (file)
@@ -7,8 +7,8 @@
 #include "music.h"
 #include "upkg.h"
 
-#define U_MUSIC_GET_PRIV(o) \
-       G_TYPE_INSTANCE_GET_PRIVATE(o, U_MUSIC_TYPE, struct music_priv)
+#define MUSIC_GET_PRIV(o) \
+       G_TYPE_INSTANCE_GET_PRIVATE(o, ENGINE_MUSIC_TYPE, struct music_priv)
 
 struct music_priv {
        unsigned type;
@@ -20,17 +20,9 @@ struct music_priv {
        unsigned long nbuf;
 };
 
-static void serializable_init(UPkgSerializable *s);
-static void exportable_init(UPkgExportable *e);
-
-G_DEFINE_TYPE_WITH_CODE(UMusic, u_music, G_TYPE_OBJECT,
-       G_IMPLEMENT_INTERFACE(UPKG_TYPE_SERIALIZABLE, serializable_init)
-       G_IMPLEMENT_INTERFACE(UPKG_TYPE_EXPORTABLE, exportable_init)
-);
-
 static int export(GObject *o, FILE *f)
 {
-       struct music_priv *priv = U_MUSIC_GET_PRIV(o);
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
        size_t left = priv->len, rc;
 
        unsigned char buf[1024];
@@ -52,7 +44,7 @@ static int export(GObject *o, FILE *f)
 
 static int export_name(GObject *o, char *buf, size_t n)
 {
-       struct music_priv *priv = U_MUSIC_GET_PRIV(o);
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
 
        return snprintf(buf, n, "%s", priv->f->name);
 }
@@ -65,8 +57,8 @@ static void exportable_init(UPkgExportable *e)
 
 static int deserialize(GObject *o, struct upkg_file *f)
 {
-       struct music_priv *priv = U_MUSIC_GET_PRIV(o);
-       UMusic *m = U_MUSIC(o);
+       struct music_priv *priv = MUSIC_GET_PRIV(o);
+       EngineMusic *m = ENGINE_MUSIC(o);
        long size;
 
        size_t rc;
@@ -107,11 +99,25 @@ static void serializable_init(UPkgSerializable *s)
        s->deserialize = deserialize;
 }
 
-static void u_music_init(UMusic *o)
+static void engine_music_init(EngineMusic *m)
 {
 }
 
-static void u_music_class_init(UMusicClass *class)
+static void engine_music_class_init(EngineMusicClass *class)
 {
        g_type_class_add_private(class, sizeof (struct music_priv));
 }
+
+static void engine_music_class_finalize(EngineMusicClass *class)
+{
+}
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED(EngineMusic, engine_music, G_TYPE_OBJECT, 0,
+       G_IMPLEMENT_INTERFACE(UPKG_TYPE_SERIALIZABLE, serializable_init)
+       G_IMPLEMENT_INTERFACE(UPKG_TYPE_EXPORTABLE, exportable_init)
+);
+
+void music_register(GTypeModule *m)
+{
+       engine_music_register_type(m);
+}
diff --git a/src/engine/music.h b/src/engine/music.h
new file mode 100644 (file)
index 0000000..92de5f8
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef MUSIC_H_
+#define MUSIC_H_
+
+#include <glib-object.h>
+
+#define ENGINE_MUSIC_TYPE (engine_music_get_type())
+#define ENGINE_MUSIC(obj) \
+       G_TYPE_CHECK_INSTANCE_CAST(obj, ENGINE_MUSIC_TYPE, EngineMusic)
+#define ENGINE_MUSIC_CLASS(class) \
+       G_TYPE_CHECK_CLASS_CAST(class, ENGINE_MUSIC_TYPE, EngineMusicClass)
+#define ENGINE_IS_MUSIC(obj) \
+       G_TYPE_CHECK_INSTANCE_TYPE(obj, ENGINE_MUSIC_TYPE)
+#define ENGINE_IS_MUSIC_CLASS(class) \
+       G_TYPE_CHECK_CLASS_TYPE(class, ENGINE_MUSIC_TYPE, EngineMusicClass)
+
+typedef struct EngineMusic      EngineMusic;
+typedef struct EngineMusicClass EngineMusicClass;
+
+struct EngineMusic {
+       GObject parent;
+};
+
+struct EngineMusicClass {
+       GObjectClass parent;
+};
+
+GType engine_music_get_type(void);
+void music_register(GTypeModule *m);
+
+#endif
index 5edc5e2b891262c005331ea4d853ed6f2313d45a..f97bc65646f946c367ef78b05bd6a96ff0b404c2 100644 (file)
@@ -1,9 +1,14 @@
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
 #include <glib-object.h>
 #include <ltdl.h>
 
 #include "module.h"
 
+G_DEFINE_TYPE(UPkgModule, upkg_module, G_TYPE_TYPE_MODULE);
+
 static unsigned initialized;
 
 static void dl_print_errors(const char *prefix)
@@ -11,8 +16,80 @@ static void dl_print_errors(const char *prefix)
        const char *err;
        while (err = lt_dlerror()) {
                if (prefix) fprintf(stderr, "%s: ", prefix);
-               puts(lt_dlerror());
+               puts(err);
+       }
+}
+
+static gboolean module_load(GTypeModule *m)
+{
+       UPkgModule *mod = UPKG_MODULE(m);
+       int (*init_func)(GTypeModule *);
+
+       mod->dl = lt_dlopenext(G_TYPE_MODULE(m)->name);
+       if (!mod->dl) {
+               dl_print_errors(__func__);
+               return FALSE;
+       }
+
+       init_func = lt_dlsym(mod->dl, "init");
+       if (!init_func || init_func(m) != 0) {
+               dl_print_errors(__func__);
+               lt_dlclose(mod->dl);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static void module_unload(GTypeModule *m)
+{
+       UPkgModule *mod = UPKG_MODULE(m);
+
+       if (lt_dlclose(mod->dl) != 0) {
+               dl_print_errors(__func__);
+       }
+}
+
+static void upkg_module_init(UPkgModule *mod)
+{
+}
+
+static void upkg_module_class_init(UPkgModuleClass *class)
+{
+       GTypeModuleClass *modclass = G_TYPE_MODULE_CLASS(class);
+
+       modclass->load   = module_load;
+       modclass->unload = module_unload;
+}
+
+UPkgModule *upkg_module_new(const char *name)
+{
+       char *name2;
+       size_t len;
+
+       if (!name) {
+               return NULL;
        }
+
+       len   = strlen(name);
+       name2 = malloc(len+1);
+       if (!name2) {
+               return NULL;
+       }
+
+       UPkgModule *mod = g_object_new(UPKG_MODULE_TYPE, NULL);
+       if (!mod) {
+               free(name2);
+               return NULL;
+       }
+
+       G_TYPE_MODULE(mod)->name = name2;
+       for (size_t i = 0; i < len; i++) {
+               name2[i] = tolower(name[i]);
+       }
+       name2[len] = 0;
+
+       return mod;
 }
 
 int module_init(void)
index ea52071779941724e4bc490bb5f7a503037e07e2..103bf266f1ccbe85708bec50f498f334fd946709 100644 (file)
@@ -1,6 +1,34 @@
 #ifndef MODULE_H_
 #define MODULE_H_
 
+#include <glib-object.h>
+#include <ltdl.h>
+
+#define UPKG_MODULE_TYPE (upkg_module_get_type())
+#define UPKG_MODULE(obj) \
+       G_TYPE_CHECK_INSTANCE_CAST(obj, UPKG_MODULE_TYPE, UPkgModule)
+#define UPKG_MODULE_CLASS(class) \
+       G_TYPE_CHECK_CLASS_CAST(class, UPKG_MODULE_TYPE, UPkgModuleClass)
+#define IS_UPKG_MODULE(obj) \
+       G_TYPE_CHECK_INSTANCE_TYPE(obj, UPKG_MODULE_TYPE)
+#define IS_UPKG_MODULE_CLASS(class) \
+       G_TYPE_CHECK_CLASS_TYPE(class, UPKG_MODULE_TYPE, UPkgModuleClass)
+
+typedef struct UPkgModule      UPkgModule;
+typedef struct UPkgModuleClass UPkgModuleClass;
+
+struct UPkgModule {
+       GTypeModule parent;
+
+       lt_dlhandle dl;
+};
+
+struct UPkgModuleClass {
+       GTypeModuleClass parent;
+};
+
+UPkgModule *upkg_module_new(const char *name);
+
 int module_init(void);
 int module_exit(void);
 
diff --git a/src/music.h b/src/music.h
deleted file mode 100644 (file)
index d3f685c..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef MUSIC_H_
-#define MUSIC_H_
-
-#include <glib-object.h>
-
-#define U_MUSIC_TYPE (u_music_get_type())
-#define U_MUSIC(obj) \
-       G_TYPE_CHECK_INSTANCE_CAST(obj, U_MUSIC_TYPE, UMusic)
-#define U_MUSIC_CLASS(class) \
-       G_TYPE_CHECK_CLASS_CAST(class, U_MUSIC_TYPE, UMusicClass)
-#define IS_U_MUSIC(obj) \
-       G_TYPE_CHECK_INSTANCE_TYPE(obj, U_MUSIC_TYPE)
-#define IS_U_MUSIC_CLASS(class) \
-       G_TYPE_CHECK_CLASS_TYPE(class, U_MUSIC_TYPE, UMusicClass)
-
-typedef struct UMusic      UMusic;
-typedef struct UMusicClass UMusicClass;
-
-enum {
-       U_MUSIC_UNKNOWN,
-       U_MUSIC_IT,
-       U_MUSIC_S3M,
-       U_MUSIC_XM,
-};
-
-struct UMusic {
-       GObject parent;
-};
-
-struct UMusicClass {
-       GObjectClass parent;
-};
-
-GType u_music_get_type(void);
-
-static inline GObject *u_music_new(void)
-{
-       return g_object_new(u_music_get_type(), NULL);
-}
-
-#endif
index a7e96bf02984fbbf21c95ac7e4d8841b86e72a85..f2ad3bc937db97dd768c6656b8f6038a0ac315ed 100644 (file)
@@ -25,7 +25,6 @@
 #include "module.h"
 #include "serializable.h"
 #include "exportable.h"
-#include "music.h"
 
 void print_upkg_flags(const char *prefix, unsigned long flags)
 {
@@ -88,7 +87,12 @@ int main(int argc, char **argv)
        printf("Exports: %lu\n", pkg->export_count);
        printf("Imports: %lu\n", pkg->import_count);
 
-       GObject *music = u_music_new();
+       UPkgModule *m = upkg_module_new("engine");
+       g_type_module_use(G_TYPE_MODULE(m));
+
+       GObject *music = g_object_new(g_type_from_name("EngineMusic"), NULL);
+       if (!music)
+               return EXIT_FAILURE;
        struct upkg_file *f = upkg_export_open(pkg, 0);
        upkg_deserialize(music, f);