Top | ![]() |
![]() |
![]() |
![]() |
#define | FM_DEFINE_MODULE() |
gboolean | (*FmModuleInitCallback) () |
#define | FM_MODULE_DEFINE_TYPE() |
#define | CHECK_MODULES() |
void | fm_module_register_type () |
void | fm_module_unregister_type () |
void | fm_modules_load () |
gboolean | fm_module_is_in_use () |
gboolean | fm_modules_add_directory () |
include
: libfm/fm.h
This implementation allows applications to use external modules and select which ones application wants to use (from none to all).
The naming scheme in examples below is strict. Replace "dummy" part in them with your real name when you trying to use those examples. Those strict example names are:
FM_MODULE_dummy_VERSION
fm_module_init_dummy
fm_module_callback_dummy
fm_module_register_dummy
To use modules application should make few things. Let say, there is some FmDummyWidget which wants to use "dummy" type of modules. First thing application should do is create a header file which all modules of that type should include:
Example 1. Sample of fm-dummy.h
1 2 3 4 5 6 7 8 9 |
#include <libfm/fm.h> #define FM_MODULE_dummy_VERSION 1 typedef struct _FmDummyInit { int (*get_new)(const char *name); } FmDummyInit; extern FmDummyInit fm_module_init_dummy; |
The FM_MODULE_dummy_VERSION is a number which should be increased each time something in FmDummyInit structure is changed. The FmDummyInit represents an interface to module. It is specific for said module type. The fm_module_init_dummy usage see below.
Second thing application should do is to create implementation of the module handling in your code:
Example 2. Sample of fm-dummy-widget.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#include "fm-dummy.h" FM_MODULE_DEFINE_TYPE(dummy, FmDummyInit, 1) static gboolean fm_module_callback_dummy(const char *name, gpointer init, int ver) { /* add module callbacks into own data list */ ....... } ....... { FmDummyInit *module; int result = -1; CHECK_MODULES(); module = _find_module("test"); if (module) result = module->get_new("test sample"); return result; } |
Third thing application should do is to register module type on the
application start, the same way as application calls fm_init()
on the
start:
1 |
fm_module_register_dummy(); |
On application terminate it is adviced to unregister module type by
calling API fm_module_unregister_type()
the same way as application
calls fm_finalize()
on exit:
1 |
fm_module_unregister_type("dummy"); |
The module itself will be easy to make. All you should do is to use
FM_DEFINE_MODULE()
macro and implement callbacks for the module
interface (see the fm-dummy.h header example above):
Example 3. Sample of module dummy/test
1 2 3 4 5 6 7 8 9 10 11 12 |
#include "fm-dummy.h" FM_DEFINE_MODULE(dummy, test) static int fm_dummy_test_get_new(const char *name) { /* implementation */ } FmDummyInit fm_module_init_dummy = { fm_dummy_test_get_new; }; |
The fm_module_init_dummy should be exactly the same structure that is defined in the header file above.
Note that modules are scanned and loaded only once per application run for simplicity and reliability reasons (in fact, deletion of a module that have some code running in another thread may lead to some unpredictable problems). Therefore if you have any module changed you have to restart the application before it see your change.
#define FM_DEFINE_MODULE(_type_, _name_)
Macro used in module definition. Module should have module specific
structure: if type
is vfs then it should be fm_module_init_vfs. See
specific header file for some `extern' definition.
gboolean (*FmModuleInitCallback) (const char *key
,gpointer init_data
,int version
);
This API is used to make callback from the modules loader to the implementation which uses module so the implementation may do required checks and add module to own list of supported data. This callback will be done in default main context.
key |
the module name as key value for the type |
|
init_data |
module type specific initialization data |
|
version |
version of loaded module |
Since: 1.2.0
#define FM_MODULE_DEFINE_TYPE(_type_, _struct_, _minver_)
Macro used in module caller. Callback is ran when matched module is
found, it should return TRUE
on success.
void fm_module_register_type (const char *type
,int minver
,int maxver
,FmModuleInitCallback cb
);
Registers type
into the modules loader. The modules loader will call
cb
routine when module that supports the type
was found within the
libfm modules directory. The scanning for modules will be done after
some timeout after last call to fm_module_register_type()
so this API
should be used at application start before any possible modules usage
may appear.
type |
module type, unique for the application |
|
minver |
minimum supported module version |
|
maxver |
maximum supported module version |
|
cb |
the callback used to inform about found module |
Since: 1.2.0
void
fm_module_unregister_type (const char *type
);
Frees any resources that were allocated previously on the call to
fm_module_register_type()
API, including code of the modules. After
this call any usage of data from callbacks will be invalid and the
most possibly lead to crash so it might be called only on finalizing
the application data.
Since: 1.2.0
void
fm_modules_load (void
);
Forces scanning the libfm modules for existing modules. Any calls to
fm_module_register_type()
after this will have no effect.
Since: 1.2.0
gboolean fm_module_is_in_use (const char *type
,const char *name
);
Checks if specified module is found and successfully loaded.
Since: 1.2.0
gboolean
fm_modules_add_directory (const char *path
);
Adds an application-specific directory path
to be used later for
scanning for modules. The path
should be absolute UNIX path.
Since: 1.2.0