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 free_func);
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@lists.geany.org https://lists.geany.org/cgi-bin/mailman/listinfo/devel