mcabber/doc/HOWTO_modules.txt
changeset 1752 4a7c7900f600
parent 1735 5093b5ca1572
child 1754 d8442bcb33b7
equal deleted inserted replaced
1751:c25f95b98377 1752:4a7c7900f600
    15   #include <mcabber/modules.h>
    15   #include <mcabber/modules.h>
    16 
    16 
    17   typedef void (*module_init_t)(void);
    17   typedef void (*module_init_t)(void);
    18   typedef void (*module_uninit_t)(void);
    18   typedef void (*module_uninit_t)(void);
    19 
    19 
    20   typedef struct {
    20   typedef struct module_info_struct module_info_t;
    21     const gchar      *mcabber_version;
    21   struct module_info_struct {
       
    22     const gchar      *branch;
    22     module_init_t     init;
    23     module_init_t     init;
    23     module_uninit_t   uninit;
    24     module_uninit_t   uninit;
    24     const gchar     **requires;
    25     const gchar     **requires;
    25   } module_info_t;
    26     guint             api;
       
    27     const gchar      *version;
       
    28     const gchar      *description;
       
    29     module_info_t    *next;
       
    30   };
    26 --------------------------------------------------------
    31 --------------------------------------------------------
    27 
    32 
    28 Callbacks init and uninit will be called after module
    33 Callbacks init and uninit will be called after module
    29 and it's dependencies loading. 'requires' should contain
    34 and it's dependencies loading. 'requires' can contain a
    30 NULL-terminated list of module names, that should be loaded
    35 NULL-terminated list of module names, that should be loaded
    31 before this. 'mcabber_version' is required and should contain
    36 before this. 'branch' and 'api' are required and should
    32 mcabber version, that this module is designed to work with.
    37 contain mcabber branch and api version, that this module is
    33 Three other fields may be NULL.
    38 designed to work with. For these values see ChangeLog.api.
       
    39 'version' and 'description' fields are optional and just
       
    40 provide user with additional information about module.
       
    41 'description' field can contain newlines. 'next' field can
       
    42 contain pointer to the next struct with another branch of
       
    43 mcabber, if your module can work with multiple branches.
    34 
    44 
    35 To load modules, mcabber uses glib's GModule, thus, in your
    45 To load modules, mcabber uses glib's GModule, thus, in your
    36 module you can also use functions
    46 module you can also use functions
    37 
    47 
    38 --------------------------------------------------------
    48 --------------------------------------------------------
    74  - check if module is present, and if present just
    84  - check if module is present, and if present just
    75    increase it's reference count
    85    increase it's reference count
    76  - load .so via glib (and call g_module_check_init, if
    86  - load .so via glib (and call g_module_check_init, if
    77    present)
    87    present)
    78  - check for information structure presence
    88  - check for information structure presence
    79  - check target mcabber version compatibility
    89  - find suitable branch and check api version
       
    90    compatibility
    80  - load modules, that this module requires (note, that
    91  - load modules, that this module requires (note, that
    81    dependency problems will be reported as error
    92    dependency problems will be reported as error
    82    invariably, force flag have no effect on this check)
    93    invariably, force flag have no effect on this check)
    83  - module placed into a list of modules
    94  - module placed into a list of modules
    84  - module init routine is called
    95  - module init routine is called
   319 {
   330 {
   320 	scr_LogPrint (LPRINT_NORMAL, "Bye, World!");
   331 	scr_LogPrint (LPRINT_NORMAL, "Bye, World!");
   321 }
   332 }
   322 
   333 
   323 module_info_t info_hello = {
   334 module_info_t info_hello = {
   324 	.mcabber_version = "0.10.0",
   335 	.branch          = "dev",
       
   336 	.api             = 1,
   325 	.requires        = NULL,
   337 	.requires        = NULL,
   326 	.init            = hello_init,
   338 	.init            = hello_init,
   327 	.uninit          = hello_uninit,
   339 	.uninit          = hello_uninit,
       
   340 	.version         = "0.0.1",
       
   341 	.description     = "Hello world module\n"
       
   342 		"(as well as bye world module)",
       
   343 	.next            = NULL,
   328 };
   344 };
   329 
   345 
   330 /* The End */
   346 /* The End */
   331 --------------------------------------------------------
   347 --------------------------------------------------------
   332 
   348 
   382 {
   398 {
   383 	cmd_del ("hello");
   399 	cmd_del ("hello");
   384 }
   400 }
   385 
   401 
   386 module_info_t hello_info = {
   402 module_info_t hello_info = {
   387 	.mcabber_version = "0.10.0",
   403 	.branch          = "dev",
       
   404 	.api             = 1,
   388 	.requires        = NULL,
   405 	.requires        = NULL,
   389 	.init            = hello_init,
   406 	.init            = hello_init,
   390 	.uninit          = hello_uninit,
   407 	.uninit          = hello_uninit,
       
   408 	.version         = "0.0.2",
       
   409 	.description     = "Hello world module\n"
       
   410 		"Provides command /hello",
       
   411 	.next            = NULL,
   391 }
   412 }
   392 
   413 
   393 /* The End */
   414 /* The End */
   394 --------------------------------------------------------
   415 --------------------------------------------------------
   395 
   416 
   452 		compl_del_category (hello_cid);
   473 		compl_del_category (hello_cid);
   453 	cmd_del ("hello");
   474 	cmd_del ("hello");
   454 }
   475 }
   455 
   476 
   456 module_info_t hello_info = {
   477 module_info_t hello_info = {
   457 	.mcabber_version = "0.10.0",
   478 	.branch          = "dev",
       
   479 	.api             = 1,
   458 	.requires        = NULL,
   480 	.requires        = NULL,
   459 	.init            = hello_init,
   481 	.init            = hello_init,
   460 	.uninit          = hello_uninit,
   482 	.uninit          = hello_uninit,
       
   483 	.version         = "0.0.3",
       
   484 	.description     = "Hello world module"
       
   485 		"Provides command /hello with completion",
       
   486 	.next            = NULL,
   461 }
   487 }
   462 
   488 
   463 /* The End */
   489 /* The End */
   464 --------------------------------------------------------
   490 --------------------------------------------------------
   465 
   491 
   559 	if (beep_cid)
   585 	if (beep_cid)
   560 		compl_del_category (beep_cid);
   586 		compl_del_category (beep_cid);
   561 }
   587 }
   562 
   588 
   563 module_info_t beep_info = {
   589 module_info_t beep_info = {
   564 	.mcabber_version = "0.10.0",
   590 	.branch          = "dev",
       
   591 	.api             = 1,
   565 	.requires        = NULL,
   592 	.requires        = NULL,
   566 	.init            = beep_init,
   593 	.init            = beep_init,
   567 	.uninit          = beep_uninit,
   594 	.uninit          = beep_uninit,
       
   595 	.version         = "0.0.1",
       
   596 	.description     = "Simple beeper module\n"
       
   597 		"Recognizes option beep_enable\n"
       
   598 		"Provides command /beep",
       
   599 	.next            = NULL,
   568 }
   600 }
   569 
   601 
   570 /* The End */
   602 /* The End */
   571 --------------------------------------------------------
   603 --------------------------------------------------------
   572 
   604 
   609 #include <mcabber/modules.h>
   641 #include <mcabber/modules.h>
   610 
   642 
   611 const gchar *a_deps[] = { "b", "c", NULL };
   643 const gchar *a_deps[] = { "b", "c", NULL };
   612 
   644 
   613 module_info_t info_a = {
   645 module_info_t info_a = {
   614 	.mcabber_version = "0.10.0",
   646 	.branch          = "dev",
       
   647 	.api             = 1,
   615 	.requires        = a_deps,
   648 	.requires        = a_deps,
   616 	.init            = a_init,
   649 	.init            = a_init,
   617 	.uninit          = a_uninit,
   650 	.uninit          = a_uninit,
       
   651 	.version         = NULL,
       
   652 	.description     = NULL,
       
   653 	.next            = NULL,
   618 };
   654 };
   619 --------------------------------------------------------
   655 --------------------------------------------------------
   620 
   656 
   621 If your module needs to "authenticate" mcabber version
   657 If your module needs to "authenticate" mcabber version
   622 too, this can be done in g_module_check_init:
   658 too, this can be done in g_module_check_init:
   624 --------------------------------------------------------
   660 --------------------------------------------------------
   625 #include <glib.h>
   661 #include <glib.h>
   626 #include <gmodule.h>
   662 #include <gmodule.h>
   627 
   663 
   628 #include <mcabber/main.h>
   664 #include <mcabber/main.h>
       
   665 #include <mcabber/modules.h>
   629 
   666 
   630 const gchar *g_module_check_init (GModule *module)
   667 const gchar *g_module_check_init (GModule *module)
   631 {
   668 {
   632 	char *ver = mcabber_version ();
   669 	char *ver = mcabber_version ();
   633 
       
   634 	// ver now contains version in format
   670 	// ver now contains version in format
   635 	// X.X.X[-xxx][ (XXXXXXXXX)]
   671 	// X.X.X[-xxx][ (XXXXXXXXXXXXX)]
       
   672 	const gchar *branch = mcabber_branch;
       
   673 	guint api = mcabber_api_version;
       
   674 	const gchar *error = NULL;
       
   675 
   636 	if (...)
   676 	if (...)
   637 		return "Incompatible mcabber version";
   677 		error = "Incompatible mcabber version";
   638 
   678 
   639 	g_free (ver);
   679 	g_free (ver);
   640 	return NULL;
   680 	return error;
   641 }
   681 }
   642 --------------------------------------------------------
   682 --------------------------------------------------------
   643 
   683 
   644 Also you can use glib check_init routine to modify
   684 Also you can use glib check_init routine to modify
   645 module information, that will be checked by mcabber,
   685 module information, that will be checked by mcabber,
   646 eg. if you want your module to always pass mcabber
   686 eg. if you want your module to always pass mcabber
   647 version check, you can assign version, obtained from
   687 version check, you can assign branch information,
   648 mcabber_version() to corresponding field in your struct.
   688 obtained from mcabber_... variables to corresponding
       
   689 fields in your struct.
   649 Or you can modify your module's dependencies, though
   690 Or you can modify your module's dependencies, though
   650 direct module_load() will have the same effect, and
   691 direct module_load() will have the same effect, and
   651 can be used for optional dependencies, that your module
   692 can be used for optional dependencies, that your module
   652 can work without.
   693 can still work without.
   653 
   694 
   654 Note: remember, that g_module_check_init will be always
   695 Note: remember, that g_module_check_init will be always
   655 called, even if later module will not pass checks, thus:
   696 called, even if later module will not pass checks, thus:
   656  - do not use functions from other modules there;
   697  - do not use functions from other modules there;
   657  - provide g_module_unload to undo anything, check_init
   698  - provide g_module_unload to undo anything, check_init
   689 a more suitable version of text in question).
   730 a more suitable version of text in question).
   690 
   731 
   691   -- Myhailo Danylenko
   732   -- Myhailo Danylenko
   692   -- mailto:isbear@ukrpost.net
   733   -- mailto:isbear@ukrpost.net
   693   -- xmpp:isbear@unixzone.org.ua
   734   -- xmpp:isbear@unixzone.org.ua
   694   -- Thu, 04 Mar 2010 09:32:38 +0200
   735   -- Sat, 13 Mar 2010 12:18:17 +0200
   695 
   736