[Geany-Devel] New plugin loader mechanisms
Thomas Martitz
kugel at xxxxx
Wed Mar 25 23:22:05 UTC 2015
Am 18.03.2015 um 22:55 schrieb Matthew Brush:
> On 15-03-18 09:42 AM, Thomas Martitz wrote:
>>
>> tl;dr <-
>> Key functions
>>
>> gboolean geany_load_module(GeanyPlugin *, GModule *)
>
> What is the GModule* for? Is it a .dll that Geany opened on behalf of
> the plugin based on selection in Plugin Manager?
That's the function exported by native (C/C++) plugins that want to
register as plugins with Geany. With my proposal that's the only
function of a plugin that Geany gets through g_module_open(). Since this
only applies to native shared libraries, the corresponding GModule is
passed.
This function is similar to libpeas' peas_register_types().
>
>> gboolean geany_plugin_register(GeanyPlugin *, gint api, gint abi,
>> PluginHooks *(see below), gpointer)
>>
>> The plugin defines a single global function,
>> geany_load_module(GeanyPlugin *, GModule *). This is the only function
>> that geany learns about using g_module_symbol(). And the only thing this
>> function ought to do is to call geany_plugin_register(). This does 4
>> things
>> 1) Provide the plugin handle to the plugin very early
>> 2) Perform abi and abi checks, so this is finally done inside geany.
>> Added bonus is that geany knows the requested api and can possibly apply
>> backcompat workarounds on a per plugin basis (instead of globally), warn
>> about very old plugins or even deny loading them.
>> 3) Register the remaining hooks and callbacks (see below)
>> 4) Associate a userdata pointer to the plugin, geany will pass this
>> pointer back to future calls into the plugin (good for proxies)
>>
>> In the future geany_plugin_register should be able to be used to
>> register plugins recursivly, by passing the appropriate GeanyPlugin
>> pointer, i.e. plugin A should be able to call
>> geany_plugin_register(plugin_B, ...) to realize pluxies.
>>
>> Now to the plugin hooks:
>> typedef struct _PluginHooks
>> {
>> PluginCallback *callbacks;
>> void (*set_info) (GeanyPlugin *plugin, gpointer pdata);
>> void (*init) (GeanyPlugin *plugin, gpointer pdata);
>> GtkWidget* (*configure) (GeanyPlugin *plugin, GtkDialog *dialog,
>> gpointer pdata);
>> void (*help) (GeanyPlugin *plugin, gpointer pdata);
>> void (*cleanup) (GeanyPlugin *plugin, gpointer pdata);
>> }
>> PluginHooks;
>>
>
> What if instead of PluginHooks it was called `Plugin` (GeanyPlugin is
> taken, so for this discussion I'll use `Plugin` :) and instead of just
> the callback function pointers it contained the (possibly
> sub-)plugin's info, like this:
Plugin is also taken inside Geany :)
>
> ```
> typedef struct
> {
> const char *name;
> const char *version;
> const char *author;
> const char *description;
> unsigned api_min;
> unsigned abi_ver;
> void *plugin_data; // pdata/plugin context
>
> bool (*init) (Plugin*);
> GtkWidget (*configure) (Plugin,GtkDialog*);
> gchar* (*help) (Plugin*); // if not NULL ret, show URL in browser
> bool (*deinit) (Plugin*); // could signal unloading problem
> }
> Plugin;
> ```
>
> Then the "register" function could be like:
>
> ```
> bool plugin_register (GeanyPlugin *module, // geany's plugin context
> Plugin *plugin); // real/sub-plugin ctx
> ```
>
> Inside a normal plugin it could do:
>
> ```
> static Plugin my_plugin = {
> .name = "Foo",
> .version = "0.1",
> .author = "Me",
> .description = "Foo plugin",
> .api_min = 200,
> .abi_ver = GEANY_ABI_VERSION,
> .init = my_plugin_init,
> .configure = my_plugin_configure,
> .help = my_plugin_help,
> .deinit = my_plugin_cleanup,
> };
>
> G_MODULE_EXPORT
> bool plugin_load_module (GeanyPlugin *module_plugin)
> {
> return plugin_register (module_plugin, &my_plugin);
> }
> ```
>
> Or for a proxying-type plugin (ex. GeanyPy/GeanyLua):
>
> ```
> G_MODULE_EXPORT
> bool plugin_load_module (GeanyPlugin *module_plugin)
> {
> Plugin *plug = g_new0 (Plugin, 1);
> *plug = my_plugin;
> plug->name = "Joe's plugin";
> plug->version = etc...
> plug->plugin_data = PyObject_New(...); // or lua_new() or whatever
> return plugin_register (module_plugin, plug);
> }
> ```
>
> Just some ideas based on yours and mine previous work around this.
> There's many ways to skin this cat :)
That's only a slightly different version of my proposal, it's
fundamentally the same. Glad you like it :D
Thanks for your suggestion to make the plugin_set_info() obsolete and
move filing the info fields before geany_plugin_register(). I will
incoperate that into my v2 of my proposal.
Best regards
More information about the Devel
mailing list