How to properly reuse object pointers to widgets in GTK 3?

Suppose I have some widgets that I want to reuse their pointers, as they are dynamically allocated and removed. Example:

GtkWidget *widget1;
GtkWidget *widget2;
GtkWidget *widget3;
 
int main()
{
    widget1 = gtk_new_type1_widget();
    widget2 = gtk_new_type2_widget();
    widget3 = gtk_new_type3_widget();

    gtk_init(0, NULL);

    //All other GTK initializing stuff, window
    //creation and widgets loading from file...

    gtk_main();

    return 0;


}

Now suppose that I want to reuse widget1, widget2 and widget3 to point to a new widget. What is the proper to way to “free” the widgets before I allocate a new one? Do I need to call gtk_widget_destroy to clean all references? Or I can call something like g_clear_object?

Example:

gtk_widget_destroy(widget1);
g_clear_object(&widget1);
widget1 = gtk_new_type1_widget();

gtk_widget_destroy(widget2);
g_clear_object(&widget2);
widget2 = gtk_new_type2_widget();

gtk_widget_destroy(widget3);
g_clear_object(&widget3);
widget3 = gtk_new_type3_widget();

Also, a second question related to this one. If I create a function that wraps another gtk object creating function and set some properties for the objects, do I need to call g_object_unref ? Since the reference count will grow.

Example:

GtkWidget *create_widget_with_properties()
{
    GtkWidget *widget;
    widget = gtk_new_type1_widget();
    set_widget_specific_properties(widget);
    g_object_unref(widget);
    return widget;
}

Appreciate any help.

Gtk version: 3.24.20

Hello, welcome to the forums, that’s a great question. If you are creating widgets from C code and then inserting them into a container, it is not usually necessary to call g_clear_object or g_object_unref. The widgets will have a floating reference which will be consumed by the container when the widget is inserted. Setting properties on the object usually will also not increase the reference count, so you shouldn’t need to worry about it in that case either. You can just write something else into the pointer variable, and you can probably remove that extra g_object_unref.

The times you would have to worry about it is if you’ve manually called g_object_ref_sink on the widget yourself, although I can’t think of why you would ever need to do that in C outside of writing your own container widget. If you did, you would probably want to call g_set_object because it handles the unref on the old object and the ref on the new object in one single call.

1 Like

This is the main reason why pointers are so hard to be understood in C.
The way one understand the things happens there, is the way they are dealing with them.

Try to understand the C way and not the programmer (by the way, C Standard does not even mandate something about the Stack and the Heap in that manner) when it comes to pointers and memory allocation.

The thing which happens is, that you as programmer you are making a request in your code using your compiler as a Tool, to operate with your operating system to see if there is some available memory for you.
If you get it, your pointer it used to point to that memory location.

If there is no memory available, during some problems, you get nothing and your pointer is NULL (which by the way should always set to NULL before gets used to guarantee that you have a NULL pointer if something goes wrong).

Now, if one understands this than, it is clear where and how the memory clean should take place.
The same story should apply in GTK as well, A pointer is a pointer, and you are not interested in the pointer itself.

You are interested where the Pointer points and what happens there.
If you understand this, you know what you have to do.
Like @jfrancis said, a good start for you would be to read about floating reference.

PS:
this is a generally pointed answer and not directly to you, please do not take it personally.

Thanks for the reply!
So I don’t need the g_object_unref in the case of a custom widget creation function?

In the case of a container, i need just to remove using gtk_container_remove ( or any of its class specific friends)?

I’m developing an application that has an intense reuse of widgets, actually an array of widgets and usually they are in a grid. I thinks its easier if you could tell if the following sample application is coded properly in a GTK sense:

//All libs needed
//...
#define NUMBER_OF_WIDGETS 10

GtkWidget *grid;
GtkWidget **widget_array;


GtkWidget *create_widget_with_properties(some_propety_type some_property);

//Example callback that clean the grid and
//put different widgets there
static void on_change_widgets_button_click(GtkButton* self, gpointer user_data)
{
	int j;

	for(j = 0; j < NUMBER_OF_WIDGETS; j++ )
    {
    	//Clean grid
    	gtk_widget_destroy(gtk_grid_get_child_at(grid, 0, j));
    	//Here that I'm not sure if I need to call
    	//g_clear_object for widget_array[j].
    	
    	widget_array[j] = NULL;

    	//Create new different widgets and repopulate the grid
    	widget_array[j] = create_widget_with_properties(different_property_value);
    	gtk_grid_attach(grid, 0, j , 1, 1);
    }

}


int main()
{
    
	int j;

    gtk_init(0, NULL);

    //All other GTK initializing stuff, window
    //creation and widgets loading from file...

    grid = gtk_grid_new();
    widget_array = calloc(sizeof*widget_array, NUMBER_OF_WIDGETS);

    for(j = 0; j < NUMBER_OF_WIDGETS; j++ )
    {
    	widget_array[j] = create_widget_with_properties(some_property_value);
    	gtk_grid_attach(grid, 0, j , 1, 1);
    }


    gtk_main();

    free(widget_array);

    return 0;


}

GtkWidget *create_widget_with_properties(some_property_type some_property)
{
    GtkWidget *widget;
    widget = gtk_new_some_type_widget();
    set_widget_specific_properties(widget, some_property);
    return widget;
}

Suppose I have the widgets in the widgets array but they aren’t attached to the grid, how do I free them? call
gtk_widget_destroy on each of them? g_clear_object?

Thanks for the answer! I didn’t take it personally, appreciate that you cared. Maybe I haven’t make myself clear when I said that they are dynamically allocated. I was talking about specifically of the GTK case, I mean, when I call a function to generate a widget it needs to allocate some memory to exist and the pointer just points to the memory allocated. Next time I’ll pay more attention! Anyway, thanks for the explanation!

I did understand you, but until you do not fix your C language approach, you will always face this GTK problems.

.
.

Question:
is there any reason to think that CASE 1) is different from CASE 2) and should be treated according to its difference?

#include <gtk/gtk.h>

GtkWidget *create_button ( const gchar *const label, const gboolean property );

int main ( void )
{
    GtkWidget *window;
    GtkWidget *grid;
    GtkWidget *button;

    /// ***
    gtk_init ( 0, NULL );

    /// ***
    window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
    gtk_window_set_default_size ( GTK_WINDOW ( window ), 200, 200 );

    /// ***
    g_signal_connect ( window, "destroy", gtk_main_quit, NULL );

    /// ***
    grid = gtk_grid_new();
    gtk_container_add ( GTK_CONTAINER ( window ), grid );

    /// ***
    for ( gint i = 0 ; i < 6 ; i++ )
    {
        /// *** CASE 1)
        ///button = gtk_button_new_with_label ( "Click" );
        ///g_object_set ( button, "use-underline", TRUE, NULL );


        /// *** CASE 2)
        ///button = create_button ( "Click", TRUE );

        /// ***
        gtk_grid_attach ( GTK_GRID ( grid ), button, i, 0, 1, 1 );

        /// ***
        ///g_object_unref ( button );
    }

    /// ***
    ///g_object_unref ( button );

    /// ***
    gtk_widget_show_all ( window );

    /// ***
    gtk_main();
}

GtkWidget *create_button ( const gchar *const label, const gboolean property )
{
    GtkWidget *button;

    /// ***
    button = gtk_button_new_with_label ( label );

    /// ***
    g_object_set ( button, "use-underline", property, NULL );

    /// ***
    return button;
}

Now, If you’re still not sure about it, then try to call :

/// ***
g_object_unref ( button );

Inside that for loop after the gtk_grid_attach call (uncomment it) and see what happens.
Do the same before the gtk_widget_show_all call.

1 Like

Thanks to your example, the floating ref link by @jfrancis and also this document I could understand what to do. I didn’t now about the reference count concept, as a result, I couldn’t understand the floating reference concept. In my case gtk_widget_destroy() or gtk_container_remove () will do the job.

GTK team could put a recommendation to read the floating reference page in the main GTK3 docs page. The link to the page just appears in the GOBJECT docs.

Anyway, thanks everybody!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.