[Geany-Devel] New plugin loader mechanisms

Thomas Martitz kugel at xxxxx
Sat Apr 4 09:36:25 UTC 2015

Am 30.03.2015 um 23:07 schrieb Thomas Martitz:
> Am 30.03.2015 um 14:57 schrieb Colomban Wendling:
>> If `pdata` is provided in geany_plugin_register(), how does it get
>> released?  If it has to be a pointer to static data it's a bit limiting,
>> and forces use of (static) globals, which is one thing that this new API
>> tries to avoid, doesn't it?  We could also ask for a GDestroyNotify, but
>> that's an additional arg we might not need.
>> And also, providing the pdata in geany_load_module() might mean memory
>> allocation, allocation that might never be used if the plugin isn't
>> activated.
>> OTOH, if `pdata` is a member of GeanyPlugin, it can be allocated in
>> init() and freed in cleanup() without having to tell Geany how it has to
>> free it.
> I see what you mean. Indeed, this could be a problem.
> I wanted the pdata parameter such that it is friendly to language 
> bindings. This doesn't work if the user_data is hidden down in some 
> other structs passed as parameter. For example, I wanted to make it 
> possible to use vala member functions classes directly as plugin 
> hooks. And this works, however there is indeed a leak. I have a 
> prototype, see below.
> Considering this use case I would rather take the GDestroyNotify than 
> hiding down pdata in another param. Passing it to 
> geany_plugin_register() also allows for using a member function for 
> the init() hook already.
> What do you think?

Replying to self after having thought about it a bit more.

Since I do want to maintain the ability to set the data in 
geany_load_module(), or rather just before the plugin's init() (to 
enable the use case cited below), but also at the same time still allow 
it to be also set in the plugin's init() (some plugins don't want 
expensive allocs before init()) AND definitely pass the pointer as a 
separate parameter, the only think I came up with is a separate API 
function to set the data, including the destroy notify. So I have now:

geany_plugin_register(GeanyPlugin *, gint api, gint min_api, gint abi, 
GeanyPluginHooks *); /* pdata param is removed */
geany_plugin_set_data(GeanyPlugin *, gpointer pdata, GDestroyNotify 

geany_plugin_set_data() can be called before the plugin's init, or 
within, or any later. It'll set the data that is passed to all the hooks 
(NULL is passed if geany_plugin_set_data() was never called). The 
GDestroyNotify is called before the plugin is unloaded. Most importantly 
it is also called if geany_plugin_set_data() was called before init() 
and the plugin did not became activated at all.

I have successfully prototyped that the below Vala example can work 
without leaks using the separate API function:

-    p.register(Geany.API_VERSION, 224, Geany.ABI_VERSION,
-        ref hooks, new Tester() /* LEAK */);
+    p.register(Geany.API_VERSION, 224, Geany.ABI_VERSION, ref hooks);
+    p.set_data(new Tester() /* no leak, g_object_unref is automatically 
passed as destroy notify */);

Is that sound?

Best regards

> Appendix: The prototype is like this:
> using Geany;
> class Tester
> {
>     public void init(Plugin p) { }
>     public void help(Plugin p) { /* shows a dialog */ }
>     public void cleanup(Plugin p) { }
> }
> private PluginHooks hooks;
> public bool geany_load_module(Plugin p, GLib.Module mod, int 
> geany_api_ver)
> {
>     hooks.init = Tester.init;
>     hooks.help = Tester.help;
>     hooks.cleanup = Tester.cleanup;
>     p.register(Geany.API_VERSION, 224, Geany.ABI_VERSION,
>         ref hooks, new Tester() /* LEAK */);
>     mod.make_resident();
>     /* ... */
>     return true;
> }
> _______________________________________________
> Devel mailing list
> Devel at lists.geany.org
> https://lists.geany.org/cgi-bin/mailman/listinfo/devel

More information about the Devel mailing list