I am working on a plugin written in C using Gtk for a Linux application. I only get errors when attempting to reload the plugin.
So here are the step:
Here is what I see in the console
(:121962): GLib-GObject-CRITICAL **: 00:16:43.621: cannot register existing type 'ProjectViewTreeStore'
(:121962): GLib-GObject-CRITICAL **: 00:16:43.643: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed
(:121962): GLib-CRITICAL **: 00:16:43.643: g_once_init_leave_pointer: assertion 'result != 0' failed
(:121962): GLib-GObject-CRITICAL **: 00:16:43.644: g_object_new_with_properties: assertion 'G_TYPE_IS_OBJECT (object_type)' failed
(:121962): Gtk-CRITICAL **: 00:16:43.644: gtk_tree_store_set_column_types: assertion 'GTK_IS_TREE_STORE (tree_store)' failed
Here is the code for the GtkTreeStore subclass:
#pragma once
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define PROJECT_VIEW_TYPE_TREE_STORE (project_view_tree_store_get_type())
#define PROJECT_VIEW_TREE_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PROJECT_VIEW_TYPE_TREE_STORE, ProjectViewTreeStore))
#define PROJECT_VIEW_TREE_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PROJECT_VIEW_TYPE_TREE_STORE, ProjectViewTreeStoreClass))
#define PROJECT_VIEW_IS_TREE_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PROJECT_VIEW_TYPE_TREE_STORE))
#define PROJECT_VIEW_IS_TREE_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PROJECT_VIEW_TYPE_TREE_STORE))
#define PROJECT_VIEW_TREE_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PROJECT_VIEW_TYPE_TREE_STORE, ProjectViewTreeStoreClass))
typedef struct _ProjectViewTreeStore ProjectViewTreeStore;
typedef struct _ProjectViewTreeStoreClass ProjectViewTreeStoreClass;
typedef struct _ProjectViewTreeStorePrivate ProjectViewTreeStorePrivate;
struct _ProjectViewTreeStore {
GtkTreeStore parent_instance;
ProjectViewTreeStorePrivate* priv;
};
struct _ProjectViewTreeStoreClass {
GtkTreeStoreClass parent_class;
};
ProjectViewTreeStore* project_view_tree_store_new(gint num_cols, GType* types);
void project_view_tree_store_disable_drag_first_row(ProjectViewTreeStore* store, gboolean flag);
G_END_DECLS
Source file:
#include <gtk/gtk.h>
#include "project-view-tree-store.h"
struct _ProjectViewTreeStorePrivate {
gboolean no_drag_first_row_;
};
static gboolean row_draggable(GtkTreeDragSource* drag_source, GtkTreePath* path);
static gboolean drag_data_get(GtkTreeDragSource* drag_source, GtkTreePath* path, GtkSelectionData* selection_data);
static gboolean drag_data_delete(GtkTreeDragSource* drag_source, GtkTreePath* path);
static void project_view_tree_store_dispose(GObject* object);
static void project_view_tree_store_finalize(GObject* object);
static void gtk_tree_drag_source_interface_init(GtkTreeDragSourceIface* iface) {
iface->drag_data_delete = drag_data_delete;
iface->drag_data_get = drag_data_get;
iface->row_draggable = row_draggable;
}
G_DEFINE_TYPE_WITH_CODE(ProjectViewTreeStore, project_view_tree_store, GTK_TYPE_TREE_STORE,
G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_DRAG_SOURCE, gtk_tree_drag_source_interface_init));
static void project_view_tree_store_class_init( ProjectViewTreeStoreClass* klass) {
printf("%s\n", __func__);
GObjectClass* obj_class = G_OBJECT_CLASS(klass);
obj_class->dispose = project_view_tree_store_dispose;
obj_class->finalize = project_view_tree_store_finalize;
}
static void project_view_tree_store_init(ProjectViewTreeStore* self) {
printf("%s\n", __func__);
ProjectViewTreeStorePrivate* priv = project_view_tree_store_get_instance_private(self);
self->priv = priv;
self->priv->no_drag_first_row_ = FALSE;
}
ProjectViewTreeStore* project_view_tree_store_new(gint num_cols, GType* types) {
printf("%s\n", __func__);
ProjectViewTreeStore* store;
store = g_object_new(PROJECT_VIEW_TYPE_TREE_STORE, NULL);
gtk_tree_store_set_column_types(&store->parent_instance, num_cols, types);
return store;
}
void project_view_tree_store_disable_drag_first_row(ProjectViewTreeStore* self, gboolean flag) {
printf("%s\n", __func__);
g_return_if_fail(PROJECT_VIEW_IS_TREE_STORE(self));
self->priv->no_drag_first_row_ = flag;
}
static gboolean row_draggable(GtkTreeDragSource* drag_source, GtkTreePath* path) {
ProjectViewTreeStore* store = PROJECT_VIEW_TREE_STORE(drag_source);
if (store->priv->no_drag_first_row_ && (gtk_tree_path_get_depth(path) == 1)) {
return FALSE;
}
return TRUE;
}
static gboolean drag_data_get(GtkTreeDragSource* drag_source, GtkTreePath* path, GtkSelectionData* selection_data) {
ProjectViewTreeStore* store = PROJECT_VIEW_TREE_STORE(drag_source);
return gtk_tree_drag_source_drag_data_get(GTK_TREE_DRAG_SOURCE(&store->parent_instance), path, selection_data);
}
static gboolean drag_data_delete(GtkTreeDragSource* drag_source, GtkTreePath* path) {
ProjectViewTreeStore* store = PROJECT_VIEW_TREE_STORE(drag_source);
return gtk_tree_drag_source_drag_data_delete(GTK_TREE_DRAG_SOURCE(&store->parent_instance), path);
}
static void project_view_tree_store_dispose(GObject* object) {
printf("%s\n", __func__);
G_OBJECT_CLASS(project_view_tree_store_parent_class)->dispose(object);
}
static void project_view_tree_store_finalize(GObject* object) {
printf("%s\n", __func__);
G_OBJECT_CLASS(project_view_tree_store_parent_class)->finalize(object);
}
Why is it that no error occurs on the first load? Am I missing something in the subclass?
It appears that maybe my subclass is not 100% right but I really do not know, there really isn't a good A-to-Z tutorial on subclassing Gtk widgets and even the Gtk demo code is not consistent.
Found the solution after so long. I needed the following function call
plugin_module_make_resident
in my module load function:
G_MODULE_EXPORT void geany_load_module(GeanyPlugin* plugin) {
// Step 1: set meta-data
// <snip>
// Step 2: set functions
plugin->funcs->init = projectview_v2_init;
plugin->funcs->cleanup = projectview_v2_cleanup;
plugin->funcs->configure = NULL;
plugin->funcs->help = NULL;
// Prevent segfault in plugin when it registers GTypes and gets unloaded
// and when reloaded tries to re-register the GTypes.
plugin_module_make_resident(plugin); // <-- needed this call
// Step 3: register
GEANY_PLUGIN_REGISTER(plugin, 248);
}
https://www.geany.org/manual/reference/pluginutils_8h.html#ac402e1d165036aaeb5ae1e176e536c36