1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
<html>
<body>
<h1> pcb-rnd - plugin development - creating actions </h1>
<p>
Actions are fungw functions typically implemented in C or in a script language.
Actions are used by pcb-rnd to act upon any user request - there's always
an action behind any GUI, CLI or automated operation. pcb-rnd plugins are
written in C, thus they are registering actions written in C.
<h2> Includes and other requirements</h2>
<p>
The plugin must #include "actions.h" to be able to register actions.
<p>
Registering actions require <a href="cookie.html">the standard plugin cookie</a>.
<h2> action implementation </h2>
<p>
The following example shows how an action is implemented:
<pre>
static const char pcb_acts_ActionName[] = "ActionName(arg1, arg2, [arg3]...)";
static const char pcb_acth_ActionName[] = "Help text: short description of what the action does.";
static fgw_error_t pcb_act_ActionName(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
/* process arguments */
/* implement the action */
/* return on no-error: */
PCB_ACT_IRES(0);
return 0;
}
</pre>
<p>
More on how arguments are and return value are handled can be found in the
<a href="../fungw_actions.txt">fungw action documentation</a>.
<p>
Because of historical reasons action names are in CamelCase. This is the
only context where pcb-rnd tolerates CamelCase.
<p>
A plugin is free to register any amount of actions. Action names are globally
unique within pcb-rnd. For core plugins, the maintainer of the plugin is
responsible to avoid action name collision. For external plugins, the action
name <b>must be</b> prefixed with the plugin's name.
<h2> action table </h2>
<p>
For convenience, actions are most often registered from data tables. The table
shall contain all actions provided by the plugin:
<pre>
static const pcb_action_t <i>pluginname</i>_action_list[] = {
{"Action1", pcb_act_Action1, pcb_acth_Action1, pcb_acts_Action1},
{"Action2", pcb_act_Action2, pcb_acth_Action2, pcb_acts_Action2}
};
</pre>
<p>
The action name in the first column must be unique. If an action has
alternative names (e.g. shorthands), multiple lines may contain the
same pcb_act* fields with only the name differing. If multiple actions
are implemented in the same function (that e.g. looks at argv[0] to
decide which one was invoked), multiple lines may contain the same
pcb_act_ function, with different name and help/syntax text.
In the very unlikely case multiple action functions have the same
syntax or help, the same pcb_acth_ and/or pcb_acts_ can be used in multiple
rows of the table.
<p>
The table should be placed after the last action to avoid action
function/help/syntax forward declarations. Most often the table is placed
right above the check_ver callback.
<h2> action registration on init </h2>
<p>
Invoke macro
<b>PCB_REGISTER_ACTIONS(<i>pluginname</i>_action_list, <i>pluginname</i>_cookie)</b>
again, from the init callback. It requires <a href="cookie.html">the
standard plugin cookie</a>.
<p>
In practice, the plugin init will look like this:
<pre>
int pplg_init_expfeat(void)
{
PCB_API_CHK_VER;
PCB_REGISTER_ACTIONS(<i>pluginname</i>_action_list, <i>pluginname</i>_cookie)
return 0;
}
</pre>
<h2> action removal on uninit </h2>
<p>
When the plugin is uninitialized, all actions must be removed (to avoid
dangling function pointers after a dynamic plugin unload). This is normally
done by calling
<pre>
pcb_remove_actions_by_cookie(<i>pluginname</i>_cookie);
</pre>
from the plugin's uninit callback.
</body>
</html>
|