diff --git a/docs/reference/gmodule/gmodule.toml.in b/docs/reference/gmodule/gmodule.toml.in index 7f937aa33..46f1efd1d 100644 --- a/docs/reference/gmodule/gmodule.toml.in +++ b/docs/reference/gmodule/gmodule.toml.in @@ -43,6 +43,7 @@ base_url = "https://gitlab.gnome.org/GNOME/glib/-/blob/HEAD/" urlmap_file = "urlmap.js" # The same order will be used when generating the index content_files = [ + "modules.md", ] content_images = [ ] diff --git a/docs/reference/gmodule/meson.build b/docs/reference/gmodule/meson.build index 42478418e..026dc8a70 100644 --- a/docs/reference/gmodule/meson.build +++ b/docs/reference/gmodule/meson.build @@ -1,4 +1,5 @@ expand_content_files = [ + 'modules.md', ] gmodule_gir = meson.current_source_dir() / 'GModule-2.0.gir' diff --git a/docs/reference/gmodule/modules.md b/docs/reference/gmodule/modules.md new file mode 100644 index 000000000..8f0eeeb4a --- /dev/null +++ b/docs/reference/gmodule/modules.md @@ -0,0 +1,92 @@ +Title: Dynamic Loading of Modules + +## Dynamic Loading of Modules + +These functions provide a portable way to dynamically load object files +(commonly known as 'plug-ins'). The current implementation supports all +systems that provide an implementation of `dlopen()` (e.g. Linux/Sun), as +well as Windows platforms via DLLs. + +A program which wants to use these functions must be linked to the libraries +output by the command: + + pkg-config --libs gmodule-2.0 + +To use them you must first determine whether dynamic loading is supported on +the platform by calling [`func@GModule.Module.supported`]. If it is, you can +open a module with [`func@GModule.Module.open`], find the module's symbols +(e.g. function names) with [`method@GModule.Module.symbol`], and later close +the module with [`method@GModule.Module.close`]. +[`method@GModule.Module.name`] will return the file name of a currently +opened module. + +If any of the above functions fail, the error status can be found with +[`func@GModule.Module.error`]. + +The `GModule` implementation features reference counting for opened modules, +and supports hook functions within a module which are called when the module +is loaded and unloaded (see [callback@GModule.ModuleCheckInit] and +[callback@GModule.ModuleUnload]). + +If your module introduces static data to common subsystems in the running +program, e.g. through calling API like: + +```c +static GQuark my_module_quark = + g_quark_from_static_string ("my-module-stuff"); +``` + +it must ensure that it is never unloaded, by calling +[`method@GModule.Module.make_resident`]. + +### Calling a function defined in a GModule + +```c +// the function signature for 'say_hello' +typedef void (* SayHelloFunc) (const char *message); + +gboolean +just_say_hello (const char *filename, GError **error) +{ + SayHelloFunc say_hello; + GModule *module; + + module = g_module_open (filename, G_MODULE_BIND_LAZY); + if (module == NULL) + { + g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH, + "%s", g_module_error ()); + return FALSE; + } + + if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello)) + { + g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN, + "%s: %s", filename, g_module_error ()); + + if (!g_module_close (module)) + g_warning ("%s: %s", filename, g_module_error ()); + + return FALSE; + } + + if (say_hello == NULL) + { + g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN, + "symbol say_hello is NULL"); + + if (!g_module_close (module)) + g_warning ("%s: %s", filename, g_module_error ()); + + return FALSE; + } + + // call our function in the module + say_hello ("Hello world!"); + + if (!g_module_close (module)) + g_warning ("%s: %s", filename, g_module_error ()); + + return TRUE; + } +``` diff --git a/gmodule/gmodule.c b/gmodule/gmodule.c index aafaaf0ad..87f67846a 100644 --- a/gmodule/gmodule.c +++ b/gmodule/gmodule.c @@ -52,84 +52,6 @@ #include "gmoduleconf.h" #include "gstdio.h" -/** - * SECTION:modules - * @title: Dynamic Loading of Modules - * @short_description: portable method for dynamically loading 'plug-ins' - * - * These functions provide a portable way to dynamically load object files - * (commonly known as 'plug-ins'). The current implementation supports all - * systems that provide an implementation of dlopen() (e.g. Linux/Sun), as - * well as Windows platforms via DLLs. - * - * A program which wants to use these functions must be linked to the - * libraries output by the command `pkg-config --libs gmodule-2.0`. - * - * To use them you must first determine whether dynamic loading - * is supported on the platform by calling g_module_supported(). - * If it is, you can open a module with g_module_open(), - * find the module's symbols (e.g. function names) with g_module_symbol(), - * and later close the module with g_module_close(). - * g_module_name() will return the file name of a currently opened module. - * - * If any of the above functions fail, the error status can be found with - * g_module_error(). - * - * The #GModule implementation features reference counting for opened modules, - * and supports hook functions within a module which are called when the - * module is loaded and unloaded (see #GModuleCheckInit and #GModuleUnload). - * - * If your module introduces static data to common subsystems in the running - * program, e.g. through calling - * `g_quark_from_static_string ("my-module-stuff")`, - * it must ensure that it is never unloaded, by calling g_module_make_resident(). - * - * Example: Calling a function defined in a GModule - * |[ - * // the function signature for 'say_hello' - * typedef void (* SayHelloFunc) (const char *message); - * - * gboolean - * just_say_hello (const char *filename, GError **error) - * { - * SayHelloFunc say_hello; - * GModule *module; - * - * module = g_module_open (filename, G_MODULE_BIND_LAZY); - * if (!module) - * { - * g_set_error (error, FOO_ERROR, FOO_ERROR_BLAH, - * "%s", g_module_error ()); - * return FALSE; - * } - * - * if (!g_module_symbol (module, "say_hello", (gpointer *)&say_hello)) - * { - * g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN, - * "%s: %s", filename, g_module_error ()); - * if (!g_module_close (module)) - * g_warning ("%s: %s", filename, g_module_error ()); - * return FALSE; - * } - * - * if (say_hello == NULL) - * { - * g_set_error (error, SAY_ERROR, SAY_ERROR_OPEN, - * "symbol say_hello is NULL"); - * if (!g_module_close (module)) - * g_warning ("%s: %s", filename, g_module_error ()); - * return FALSE; - * } - * - * // call our function in the module - * say_hello ("Hello world!"); - * - * if (!g_module_close (module)) - * g_warning ("%s: %s", filename, g_module_error ()); - * return TRUE; - * } - * ]| - */ /** * GModule: