From 90b53df329f9a114770dccab6b7e41f9094dfac9 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Tue, 9 Jun 2009 18:49:37 -0400 Subject: [PATCH] Implement dynamic loading of modules. --- .gitignore | 2 + src/Makefile.am | 6 ++- src/engine/Makefile.inc | 7 ++++ src/engine/engine.c | 12 ++++++ src/{ => engine}/music.c | 38 +++++++++++-------- src/engine/music.h | 30 +++++++++++++++ src/module.c | 79 +++++++++++++++++++++++++++++++++++++++- src/module.h | 28 ++++++++++++++ src/music.h | 41 --------------------- src/upkg.c | 8 +++- 10 files changed, 189 insertions(+), 62 deletions(-) create mode 100644 src/engine/Makefile.inc create mode 100644 src/engine/engine.c rename src/{ => engine}/music.c (75%) create mode 100644 src/engine/music.h delete mode 100644 src/music.h diff --git a/.gitignore b/.gitignore index 527fdf7..03e7f99 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/src/Makefile.am b/src/Makefile.am index 8b35676..436203e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 index 0000000..62ad702 --- /dev/null +++ b/src/engine/Makefile.inc @@ -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 index 0000000..732a94a --- /dev/null +++ b/src/engine/engine.c @@ -0,0 +1,12 @@ +#include +#include + +#include "music.h" + +#define init engine_LTX_init + +int init(GTypeModule *m) +{ + music_register(m); + return 0; +} diff --git a/src/music.c b/src/engine/music.c similarity index 75% rename from src/music.c rename to src/engine/music.c index 4c64a7b..0c0cdf8 100644 --- a/src/music.c +++ b/src/engine/music.c @@ -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 index 0000000..92de5f8 --- /dev/null +++ b/src/engine/music.h @@ -0,0 +1,30 @@ +#ifndef MUSIC_H_ +#define MUSIC_H_ + +#include + +#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 diff --git a/src/module.c b/src/module.c index 5edc5e2..f97bc65 100644 --- a/src/module.c +++ b/src/module.c @@ -1,9 +1,14 @@ #include +#include +#include +#include #include #include #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) diff --git a/src/module.h b/src/module.h index ea52071..103bf26 100644 --- a/src/module.h +++ b/src/module.h @@ -1,6 +1,34 @@ #ifndef MODULE_H_ #define MODULE_H_ +#include +#include + +#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 index d3f685c..0000000 --- a/src/music.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef MUSIC_H_ -#define MUSIC_H_ - -#include - -#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 diff --git a/src/upkg.c b/src/upkg.c index a7e96bf..f2ad3bc 100644 --- a/src/upkg.c +++ b/src/upkg.c @@ -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); -- 2.43.0