From 52e1edf910c3af1e3a741e899364c8fb1aebdab5 Mon Sep 17 00:00:00 2001 From: Kolan Sh Date: Fri, 12 Sep 2014 16:37:42 +0400 Subject: [PATCH] Vala: TypeModuleSample(CrossCompilation) and TypeModule/ added. --- vala/TypeModuleSample/loader.vala | 55 ++++++++++++++++++++++++++ vala/TypeModuleSample/plugin.vala | 14 +++++++ vala/TypeModuleSample/run.sh | 15 +++++++ vala/TypeModules/main.vala | 45 +++++++++++++++++++++ vala/TypeModules/plugin-interface.vala | 3 ++ vala/TypeModules/plugin.vala | 11 ++++++ vala/TypeModules/run.sh | 21 ++++++++++ 7 files changed, 164 insertions(+) create mode 100644 vala/TypeModuleSample/loader.vala create mode 100644 vala/TypeModuleSample/plugin.vala create mode 100755 vala/TypeModuleSample/run.sh create mode 100644 vala/TypeModules/main.vala create mode 100644 vala/TypeModules/plugin-interface.vala create mode 100644 vala/TypeModules/plugin.vala create mode 100755 vala/TypeModules/run.sh diff --git a/vala/TypeModuleSample/loader.vala b/vala/TypeModuleSample/loader.vala new file mode 100644 index 0000000..aa89a5d --- /dev/null +++ b/vala/TypeModuleSample/loader.vala @@ -0,0 +1,55 @@ +class MyModule : TypeModule +{ + [CCode (has_target = false)] + private delegate Type PluginInitFunc (TypeModule module); + + private GLib.Module module = null; + + private string name = null; + + public MyModule (string name) { + this.name = name; + } + + public override bool load () { + string path = Module.build_path (Environment.get_variable ("PWD"), name); + module = Module.open (path, GLib.ModuleFlags.BIND_LAZY); + if (null == module) { + error ("Module not found"); + } + + void * plugin_init = null; + if (! module.symbol ("plugin_init", out plugin_init)) { + error ("No such symbol"); + } + + ((PluginInitFunc) plugin_init) (this); + + return true; + } + + public override void unload () { + if (module != null) + message ("Library unloaded"); + module = null; + } +} + +// Never unref instance of GTypeModule +// http://www.lanedo.com/~mitch/module-system-talk-guadec-2006/Module-System-Talk-Guadec-2006.pdf +static TypeModule module = null; + +int main () +{ + module = new MyModule ("plugin"); + module.load (); + + var o = GLib.Object.new (Type.from_name ("MyClass")); + + // free last instance, plugin unload + o = null; + + module.unload (); + + return 0; +} diff --git a/vala/TypeModuleSample/plugin.vala b/vala/TypeModuleSample/plugin.vala new file mode 100644 index 0000000..8f6e9a5 --- /dev/null +++ b/vala/TypeModuleSample/plugin.vala @@ -0,0 +1,14 @@ +public class MyClass : Object { + construct { + message("MyClass init"); + } + + ~MyClass() { + message("MyClass deinit"); + } +} + +[ModuleInit] +Type plugin_init(GLib.TypeModule type_module) { + return typeof(MyClass); +} diff --git a/vala/TypeModuleSample/run.sh b/vala/TypeModuleSample/run.sh new file mode 100755 index 0000000..ba948ce --- /dev/null +++ b/vala/TypeModuleSample/run.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# Cross-Platform: Works for GNU/Linux and Windows + +valac -o loader loader.vala --pkg=gmodule-2.0 +valac --ccode plugin.vala +if [[ `uname` == Linux ]]; then + libext=so + exeext= +else + libext=dll + exeext=.exe +fi +gcc -fPIC -shared -o libplugin.$libext plugin.c $(pkg-config --libs --cflags gobject-2.0 gmodule-2.0) +./loader$exeext diff --git a/vala/TypeModules/main.vala b/vala/TypeModules/main.vala new file mode 100644 index 0000000..5f7b96b --- /dev/null +++ b/vala/TypeModules/main.vala @@ -0,0 +1,45 @@ +public class PluginRegistrar : Object { + + public string path { get; private set; } + + private Type type; + private Module module; + + private delegate Type RegisterPluginFunction (Module module); + + public PluginRegistrar (string name) { + assert (Module.supported ()); + this.path = Module.build_path (Environment.get_variable ("PWD"), name); + } + + public bool load () { + stdout.printf ("Loading plugin with path: '%s'\n", path); + + module = Module.open (path, ModuleFlags.BIND_LAZY); + if (module == null) { + return false; + } + + stdout.printf ("Loaded module: '%s'\n", module.name ()); + + void* function; + module.symbol ("register_plugin", out function); + unowned RegisterPluginFunction register_plugin = (RegisterPluginFunction) function; + + type = register_plugin (module); + stdout.printf ("Plugin type: %s\n\n", type.name ()); + return true; + } + + public T new_object () { + return Object.new (type); + } +} + +void main () { + var registrar = new PluginRegistrar ("plugin"); + registrar.load (); + + var plugin = registrar.new_object (); + plugin.hello (); +} diff --git a/vala/TypeModules/plugin-interface.vala b/vala/TypeModules/plugin-interface.vala new file mode 100644 index 0000000..88b8fa5 --- /dev/null +++ b/vala/TypeModules/plugin-interface.vala @@ -0,0 +1,3 @@ +public interface TestPlugin : Object { + public abstract void hello (); +} diff --git a/vala/TypeModules/plugin.vala b/vala/TypeModules/plugin.vala new file mode 100644 index 0000000..f88ea6e --- /dev/null +++ b/vala/TypeModules/plugin.vala @@ -0,0 +1,11 @@ +class MyPlugin : Object, TestPlugin { + public void hello () { + stdout.printf ("Hello world!\n"); + } +} + +public Type register_plugin (Module module) { + // types are registered automatically + return typeof (MyPlugin); +} + diff --git a/vala/TypeModules/run.sh b/vala/TypeModules/run.sh new file mode 100755 index 0000000..d60e077 --- /dev/null +++ b/vala/TypeModules/run.sh @@ -0,0 +1,21 @@ +#!/bin/sh + +# Works under Linux only, not cross-platform + +valac --pkg gmodule-2.0 main.vala plugin-interface.vala -o main +if [[ `uname` == Linux ]]; then + libext=so + exeext= +else + libext=dll + exeext=.exe +fi +valac --pkg gmodule-2.0 -C plugin.vala plugin-interface.vala +if [[ `uname` == Linux ]]; then + gcc -shared -fPIC $(pkg-config --cflags --libs glib-2.0 gmodule-2.0) \ + -o libplugin.$libext plugin.c +else + gcc -shared -fPIC $(pkg-config --cflags --libs glib-2.0 gmodule-2.0 gobject-2.0) \ + -o libplugin.$libext plugin.c $(pkg-config --libs glib-2.0 gmodule-2.0 gobject-2.0) +fi +./main$exeext