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
- Provide the plugin handle to the plugin very early
- 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