Gtk.CClosureExpression in Vala

Hello,

I would appreciate if someone knowledgeable in vala could give us a working example or a tuturial on how to use Gtk.CClosureExpression.

I’ve read the c source of the some gkt demos and I can comprehend and use Gtk.PropertyExpression but not Gtk.CClosureExpression.

Thanks

1 Like

Looks like I have to find out on my own using the old “trials and errors” method :wink:

GtkCClosureExpression is really a C convenience API to create a GtkExpression that calls a function when the expression is evaluated, wrapped in a GClosure.

Language bindings should use GtkClosureExpression and GClosure directly, though, especially because bindings should already have some wrappers that turn the arguments of a closure into native types, as they are the same mechanism used to handle GObject signals.

1 Like

In DropDown demo c source code, I read the following

static char *
get_family_name (gpointer item)
{
  return g_strdup (pango_font_family_get_name (PANGO_FONT_FAMILY (item)));
}
// ...
expression = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
                                                0, NULL,
                                                (GCallback)get_family_name,
                                                NULL, NULL);
gtk_drop_down_set_expression (GTK_DROP_DOWN (button), expression);

I wounder how the callback get_family_name got it’s parameter item , although only the return type G_TYPE_STRING was defined in the closure creation and all other parameters are null?

The item parameter is passed by the expression to the closure. It’s a generic “instance” parameter taken from the list model, which requires it to be a GObject. You could have written get_family_name() as:

static char *
get_family_name (GObject *item)
{
   // ...
}

Or, to avoid the cast when calling pango_font_family_get_name():

static char *
get_family_name (PangoFontFamily *family)
{
  // ...
}

Since you know the item type stored in the list model used when constructing the GtkDropDown widget.

@ebassi Thanks for the explanation.
Nevertheless, I’ve a hard time transferring this concept in vala. All I get are segfaults :slight_smile:
I’ve started a repository with the code here.
I appreciate your help if you could sacrifice a few minutes of your time and review the code to point out what I’m doing wrong.
Needless to say that in the moment there are no other code in vala that use the new Gtk.Expression anywhere.

Sorry, I don’t speak Vala that much, so I’m not going to be very helpful.

I strongly recommend you join the #vala channel on irc.gnome.org and talk to the Vala developers.

@ebassi.
I will. Thank you.

I would be thankful if someone “fluent” in Vala could guide me in the right direction how to attach GLib.Closure to Gtk.Expression.
Thanks

Well there is Gtk.ClosureExpression

I’m just trying to think loudly why my example don’t work :thinking:

  1. I need to create a GLib.ListStore to hold the data that I want to display, in this example a list of all fonts in the system. I’ve successfully done that. fonts_list = new GLib.ListStore (typeof (Pango.FontFamily));.
  2. Create a new Gtk.DropDown var button = new Gtk.DropDown ();.
  3. Attach the model to the dropdown, button.set_model (fonts_list);
  4. Create a Gtk.CClosureExpression which got evaluated every time dropdown wants to display an item. This item got passed automatically form the model to the callback as @ebassi explained above .
    Gtk.Expression expression;
    expression = new Gtk.CClosureExpression (typeof (string), null, null, (Callback) get_font_family_name, null, null);
    
  5. In this case the Callback is a simple function that returns a string name of the font.
    string get_font_family_name (Pango.FontFamily font) {
        return font.get_name();
    }
    

Problem:
Unfortunately all I got is a bunch of assertions

CRITICAL **: 13:54:28.242: gtk4_demo_main_window_get_font_family_name: assertion 'font != NULL' failed

This assertion has Vala automatically inserted in the translated c code function
g_return_val_if_fail (font != NULL, NULL);

I don’t know why the item passed form the model to the closure is always null ?!!!

Could somebody point out the “unseen” bug for me?

Possibly, but it helps to have complete code sample to play with

Gtk.ListStore != GLib.ListStore, very different

@zbrown Thanks for replying. The compleat source code reside in the rep at https://github.com/aeldemery/gtk4_dropdown
I meant GLib.ListStore that was a typo.

You should be able to fix your example by making get_font_family_name static (or defining it outside of a class).

@akitouni Thank you very much.
Indeed that solved it. But I can’t understand why making the function static solved that?

Because if it’s a method the arguments of the generated function will not match the ones expected by the expression.

I guess because adding static removed the implicit this first parameter. could it be that?

That’s right. I came to this conclusion after examining the generated c code.

Now I’ve to ponder why my other example ‘gtk4_color_list’ don’t work :slight_smile:

@ebassi Shouldn’t the API pass a pointer to the sender as a first argument - like in Signals - because depending on first position makes it difficult for language bindings. The static wasn’t so obvious at first. What do you think?