[geany/geany] f25791: plugins: Replace geany_plugin_register() pdata with a separate API function
Thomas Martitz
git-noreply at xxxxx
Sun Aug 23 13:23:24 UTC 2015
Branch: refs/heads/master
Author: Thomas Martitz <kugel at rockbox.org>
Committer: Thomas Martitz <kugel at rockbox.org>
Date: Sun, 23 Aug 2015 13:23:24 UTC
Commit: f2579141bb4188d4fc97eee494ba36e809661ddf
https://github.com/geany/geany/commit/f2579141bb4188d4fc97eee494ba36e809661ddf
Log Message:
-----------
plugins: Replace geany_plugin_register() pdata with a separate API function
The API function adds a free_func parameter, and can also be called
after geany_plugin_register(), i.e. in the plugin's init() callback. This
fixes a by-design memory leak and gives greater flexibility.
Modified Paths:
--------------
src/plugindata.h
src/pluginprivate.h
src/plugins.c
src/pluginutils.c
Modified: src/plugindata.h
7 lines changed, 4 insertions(+), 3 deletions(-)
===================================================================
@@ -305,7 +305,8 @@ struct GeanyPluginFuncs
};
gboolean geany_plugin_register(GeanyPlugin *plugin, gint api_version, gint min_api_version,
- gint abi_version, gpointer pdata);
+ gint abi_version);
+void geany_plugin_set_data(GeanyPlugin *plugin, gpointer data, GDestroyNotify destroy_notify);
/** Convinience macro to register a plugin.
*
@@ -313,9 +314,9 @@ gboolean geany_plugin_register(GeanyPlugin *plugin, gint api_version, gint min_a
*
* @since 1.26 (API 225)
**/
-#define GEANY_PLUGIN_REGISTER(plugin, min_api_version, pdata) \
+#define GEANY_PLUGIN_REGISTER(plugin, min_api_version) \
geany_plugin_register((plugin), GEANY_API_VERSION, \
- (min_api_version), GEANY_ABI_VERSION, pdata)
+ (min_api_version), GEANY_ABI_VERSION)
/* Deprecated aliases */
#ifndef GEANY_DISABLE_DEPRECATED
Modified: src/pluginprivate.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -81,6 +81,7 @@ typedef struct GeanyPluginPrivate
GList *sources; /* GSources to destroy when unloading */
gpointer cb_data; /* user data passed back to functions in GeanyPluginFuncs */
+ GDestroyNotify cb_data_destroy; /* called when the plugin is unloaded, for cb_data */
LoadedFlags flags; /* bit-or of LoadedFlags */
}
GeanyPluginPrivate;
Modified: src/plugins.c
12 lines changed, 8 insertions(+), 4 deletions(-)
===================================================================
@@ -280,7 +280,6 @@ static gint cmp_plugin_names(gconstpointer a, gconstpointer b)
* @param api_version The API version the plugin is compiled against (pass GEANY_API_VERSION)
* @param min_api_version The minimum API version required by the plugin
* @param abi_version The exact ABI version the plugin is compiled against (pass GEANY_ABI_VERSION)
- * @param pdata A data pointer to store plugin-specific data, will be passed to the plugin's callbacks
*
* @return TRUE if the plugin was successfully registered. Otherwise FALSE.
*
@@ -289,7 +288,7 @@ static gint cmp_plugin_names(gconstpointer a, gconstpointer b)
**/
GEANY_API_SYMBOL
gboolean geany_plugin_register(GeanyPlugin *plugin, gint api_version, gint min_api_version,
- gint abi_version, gpointer pdata)
+ gint abi_version)
{
Plugin *p;
GeanyPluginFuncs *cbs = plugin->funcs;
@@ -531,6 +530,8 @@ plugin_new(const gchar *fname, gboolean load_plugin, gboolean add_to_list)
return plugin;
err:
+ if (plugin->cb_data_destroy)
+ plugin->cb_data_destroy(plugin->cb_data);
if (! g_module_close(module))
g_warning("%s: %s", fname, g_module_error());
g_free(plugin->filename);
@@ -646,12 +647,15 @@ plugin_free(Plugin *plugin)
plugin_cleanup(plugin);
active_plugin_list = g_list_remove(active_plugin_list, plugin);
+ plugin_list = g_list_remove(plugin_list, plugin);
+
+ /* cb_data_destroy might be plugin code and must be called before unloading the module */
+ if (plugin->cb_data_destroy)
+ plugin->cb_data_destroy(plugin->cb_data);
if (! g_module_close(plugin->module))
g_warning("%s: %s", plugin->filename, g_module_error());
- plugin_list = g_list_remove(plugin_list, plugin);
-
g_free(plugin->filename);
g_free(plugin);
plugin = NULL;
Modified: src/pluginutils.c
47 lines changed, 47 insertions(+), 0 deletions(-)
===================================================================
@@ -520,4 +520,51 @@ void plugin_builder_connect_signals(GeanyPlugin *plugin,
}
+/** Add additional data that corresponds to the plugin.
+ *
+ * This is the data pointer passed to the individual plugin callbacks. It may be
+ * called as soon as geany_plugin_register() was called with success. When the
+ * plugin is unloaded, @a free_func is invoked for the data, which connects the
+ * data to the plugin's own life time.
+ *
+ * One intended use case is to set GObjects as data and have them destroyed automatically
+ * by passing g_object_unref() as @a free_func, so that member functions can be used
+ * for the @ref GeanyPluginFuncs (via wrappers) but you can set completely custom data.
+ *
+ * Be aware that this can only be called once.
+ *
+ * @param plugin The plugin provided by Geany
+ * @param pdata The plugin's data to associate, must not be @c NULL
+ * @param free_func The destroy notify
+ *
+ * @since 1.26 (API 225)
+ */
+GEANY_API_SYMBOL
+void geany_plugin_set_data(GeanyPlugin *plugin, gpointer pdata, GDestroyNotify free_func)
+{
+ Plugin *p = plugin->priv;
+
+ g_return_if_fail(PLUGIN_LOADED_OK(p));
+ /* Do not allow calling this only to set a notify. */
+ g_return_if_fail(pdata != NULL);
+ /* The rationale to allow only setting the data once is the following:
+ * In the future we want to support proxy plugins (which bind non-C plugins to
+ * Geany's plugin api). These proxy plugins might need to own the data pointer
+ * on behalf of the proxied plugin. However, if not, then the plugin should be
+ * free to use it. This way we can make sure the plugin doesn't accidently trash
+ * its proxy.
+ *
+ * Better a more limited API now that can be opened up later than a potentially
+ * wrong one that can only be replaced by another one. */
+ if (p->cb_data != NULL || p->cb_data_destroy != NULL)
+ {
+ g_warning("Double call to %s(), ignored!", G_STRFUNC);
+ return;
+ }
+
+ p->cb_data = pdata;
+ p->cb_data_destroy = free_func;
+}
+
+
#endif
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list