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

typedef struct _Plugin {
	GTypeModule parent;

	GModule *mod;
} Plugin;
typedef GTypeModuleClass PluginClass;

G_DEFINE_TYPE (Plugin, plugin, G_TYPE_TYPE_MODULE);

static gboolean
load (Plugin *p)
{
	union {
		gpointer ptr;
		void (* init) (GTypeModule *mod);
	} m = { NULL };

	p->mod = g_module_open ("./libmod.so", G_MODULE_BIND_LOCAL);
	g_return_val_if_fail (p->mod, FALSE);
	g_module_symbol (p->mod, "init", &m.ptr);
	g_assert (m.ptr != NULL);

	m.init (G_TYPE_MODULE (p));
	g_print ("Load\n");

	return TRUE;
}

static void
unload (Plugin *p)
{
	g_module_close (p->mod);
	g_print ("Unload\n");
}

static void
plugin_class_init (PluginClass *klass)
{
	G_TYPE_MODULE_CLASS (klass)->load =
		(gboolean (*) (GTypeModule *)) load;
	G_TYPE_MODULE_CLASS (klass)->unload =
		(void (*) (GTypeModule *)) unload;
}

static void
plugin_init (Plugin *p)
{
}

int main (int argc, char *argv[])
{
	Plugin *p;

	g_type_init ();

	p = g_object_new (plugin_get_type (), NULL);
	if (g_type_module_use (G_TYPE_MODULE (p))) {
		GType t = g_type_from_name ("Parent");
		g_assert (t);
		GObject *o = g_object_new (t, NULL);
		g_object_unref (o);
		g_type_module_unuse (G_TYPE_MODULE (p));
	}

	if (g_type_module_use (G_TYPE_MODULE (p))) {
		GType t = g_type_from_name ("Child");
		g_assert (t);
		GObject *o = g_object_new (t, NULL);
		g_object_unref (o);
		g_type_module_unuse (G_TYPE_MODULE (p));
	}

	return 0;
}
