plugins: plugin loader redesign
commit721009e262e9bc279122566a60e14af0048d9094
authorThomas Martitz <kugel@rockbox.org>
Sun, 23 Aug 2015 13:23:20 +0000 (23 15:23 +0200)
committerThomas Martitz <kugel@rockbox.org>
Sun, 23 Aug 2015 13:23:20 +0000 (23 15:23 +0200)
treeceafad311cb5d1ce905ab700b240f4d07b1f3844
parent7d9264a6e7498f6ba2fc454ba0cdca29fb0cb6fb
plugins: plugin loader redesign

The old plugin loader has a number of deficiencies:

- plugins need to export a couple of callback functions into the global namespace
- plugins need to export data pointers, that are written by Geany
- the exported functions have no user_data param, so there is no way to
  pass context/state back to the plugin (it needs global storage for that)
- plugin registration is implicit, plugins have no way to not register themselves
  (it may want that due to missing runtime dependencies)
- plugins perform the ABI/API verification, and even though we provide a
  convinience wrapper, it may get that wrong

As a result, I designed a new loader with the following design principles
- semantics of callbacks should not change, but they they shouldn't be mess
  with the global namespace
- each callback receives a self-identifying param (the GeanyPlugin instance) and
  a plugin-defined data pointer for their own use
- explicit registration through a new API function
- in-core API/ABI checks

The following principles shall be left unchanged:
- The scan is done on startup and when the PM dialog is opened
- Geany allocates GeanyPluginPrivate for each plugin, and GeanyPlugin is
  a member of it
- Geany initially probes for the validity of the plugin, including file type
  and API/ABI check, thus Geany has the last word in determining what a
  plugin is
- the PM dialog is updated with the proper, translated plugin information
- the PM dialog GUI and user interaction in general is unchanged

With the redesign, plugins export a single function: geany_load_module().
This is called when the GModule is loaded. The main purpose of this function
is to call geany_plugin_register() (new API function) to register the plugin.
This is the only function that is learned about through g_module_symbol().
Within this call the plugin should
a) set the localized info fields of GeanyPlugin::info
b) pass compiled-against and minimum API version as well as compiled-against
   ABI version, to allow Geany to verify compatibility
c) pass a pointer to an instance of GeanyPluginFuncs
   which holds pointers to enhanced versions of the known callbacks (except
   configure_single which is dropped).
d) optionally pass a plugin-private data pointer for later callbacks

Enhanced means that all callbacks receive the GeanyPlugin pointer as the first
and a pdata pointer as the last. pdata is private to the plugin and is set
by geany_plugin_register().

The callbacks need (should) not be globally defined anymore, and the global
GeanyData, GeanyPlugin and GeanyFunctions pointers are ignored and not set
anymore. GeanyData is available through GeanyPlugin::geany_data.
src/plugindata.h
src/pluginprivate.h
src/plugins.c
src/pluginutils.c