模块的动态加载
模块的动态加载
这些函数提供了一种跨平台的方式动态加载对象文件(通常称为“插件”)。当前的实现支持所有提供了dlopen()
实现(例如Linux/Sun)的系统,以及通过DLLs的Windows平台。
想要使用这些函数的程序必须链接到由以下命令输出的库:
pkg-config --libs gmodule-2.0
使用它们之前,您必须首先通过调用g_module_supported()
来确定平台是否支持动态加载。如果是的话,您可以使用g_module_open()
打开一个模块,使用g_module_symbol()
查找模块的符号(例如,函数名),并最终使用g_module_close()
关闭模块。g_module_name()
将返回当前打开模块的文件名。
如果上述任何函数失败,可以使用g_module_error()
获取错误状态。
GModule
实现针对打开的模块使用引用计数,并支持模块内的钩子函数,这些函数在模块加载和卸载时被调用(见GModuleCheckInit
和GModuleUnload
)。
如果您的模块向正在运行的程序中的公共子系统引入了静态数据,例如通过调用
static GQuark my_module_quark =
g_quark_from_static_string ("my-module-stuff");
它必须通过调用g_module_make_resident()
确保它永远不会被卸载。
调用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 == 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;
}