Yesterday we got a new issue for the gintro Nim GTK bindings:
Of course that is a strange use of GtkBuilder, as he creates the GtkApplication window manually, and then inserts a child widget from builder. And the use of buildSomeUI() at all is a bit strange too. I do generally not use GtkBuilder whenever possible myself, so I can not really decide if he uses it in a wrong way, I would assume that he has seen code like this somewhere and translated that to Nim?
Well, as the error messages looked a bit strange to me, I translated his code to plain C for testing. I have put the UI description in its own file, as C does not allow raw strings, and I wanted to avoid escaping all the quotation marks. Here are the two C compatible files, b2.ui and e2.c, based on Building user interfaces: GTK 4 Reference Manual
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<object class="GtkBox" id="examplewidget">
<property name="valign">center</property>
<property name="halign">center</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkButton" id="examplebutton">
<property name="label">Hello, I am a button! I like being a button.</property>
</object>
</child>
</object>
</interface>
// gcc `pkg-config --cflags gtk4` -o test e2.c `pkg-config --libs gtk4`
#include <gtk/gtk.h>
#include <glib/gstdio.h>
static GtkBox* buildSomeUI(void)
{
GtkBuilder *builder = gtk_builder_new();
gtk_builder_add_from_file (builder, "b2.ui", NULL);
GObject *box = gtk_builder_get_object (builder, "examplewidget");
g_object_unref (builder); // this causes the issue!
return GTK_BOX(box);
}
static void
activate (GtkApplication *app, gpointer user_data)
{
GtkWidget *window = gtk_application_window_new(app);
gtk_widget_show (GTK_WIDGET (window));
GtkBox *box = buildSomeUI();
gtk_window_set_child(GTK_WINDOW(window), GTK_WIDGET(box));
}
int main (int argc, char *argv[])
{
GtkApplication *app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
int status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
When I compile and run the code I get
$ gcc `pkg-config --cflags gtk4` -o test e2.c `pkg-config --libs gtk4`
$ ./test
(test:13757): GLib-GObject-WARNING **: 10:06:53.126: invalid unclassed pointer in cast to 'GtkBox'
(test:13757): GLib-GObject-WARNING **: 10:06:53.126: invalid unclassed pointer in cast to 'GtkWidget'
(test:13757): Gtk-CRITICAL **: 10:06:53.126: gtk_window_set_child: assertion 'child == NULL || GTK_IS_WIDGET (child)' failed
The problem is “g_object_unref (builder);” in buildSomeUI(), which is executed automatically for the Nim code by Nim’s memory management system. But well, the original example from the GTK homepage executes g_object_unref (builder) as well. So where exactly is the problem? Is his code just invalid? (My guess would be, that the problem is, that he just uses the GtkBox from builder, but creates the app window manually?)