Finding the GParamSpec of an instance's property

Hi,

is there a way to obtain the GParamSpec of an instance’s property knowing its name?

Something like:

GParamSpec * my_prop = find_me_the_g_param_spec(my_object, "my_property");

Use g_object_class_find_property() to retrieve the property definition from the class pointer.

Thank you, Emmanuele. I will use g_object_class_find_property() then!

Is there any plan to add a function that does the same taking an instance instead of a class? I remember it happened to me in the past that I needed that (although I can’t recall the exact reason at the moment – as soon as I remember I will write here again).

No, there are no such plans. It’s a fairly rare thing to want to do, as pspecs are almost always only referred to from inside a class implementation, and then the code should already have direct access to the GParamSpec* pointer.

You can always get the class pointer out of an instance, so there’s literally no reason to add such a function.

Plus, retrieving a property definition is such a niche use case that it doesn’t need any sort of convenience.

Really? How? I was searching for that in the past, but I couldn’t find it.

The class-specific GET_CLASS macro, or the inline function that is generated by the G_DECLARE_* macro. They are part of the idiomatic conventions for GObject.

Alternatively, if it all fails, you can do:

GObjectClass *gobject_class =
   (GObjectClass *) ((GTypeInstance *) instance)->g_class;

which is what the class-specific GET_CLASS macro expands to, minus the run time type check.

1 Like

Ok, now I remember the case in point.

I had a composite widget with different children. Some properties of the composite widget were echoed from some of the children. So, for instance, imagine I have a GtkText child and I want my composite widget to echo four properties verbatim from this textbox, specifically "input-hints", "input-purpose", "overwrite-mode" and "visibility".

What I do is that my get_property() virtual method echoes them like this:

/*  These properties are inherited verbatim  */
case PROPERTY_INPUT_HINTS:
case PROPERTY_INPUT_PURPOSE:
case PROPERTY_OVERWRITE_MODE:
case PROPERTY_VISIBILITY:

	g_object_get_property(
		priv->textbox,
		g_param_spec_get_name(pspec),
		value
	);

	break;

My set_property() virtual method echoes them like this:

/*  These properties are inherited verbatim  */
case PROPERTY_INPUT_HINTS:
case PROPERTY_INPUT_PURPOSE:
case PROPERTY_OVERWRITE_MODE:
case PROPERTY_VISIBILITY:

	g_object_set_property(
		priv->textbox,
		g_param_spec_get_name(pspec),
		value
	);

	return;

Note that after setting the property I do not notify about it from within set_property(). What I do instead is that in my instance’s init function I add a listener to the "notify" event of the textbox that echoes the notification concerning the fact that the same property in my composite widget has changed.

Basically if you set the "input-purpose" property of my composite widget the following happens:

  1. The "input-purpose" property of the GtkText child is set accordingly
  2. The GtkText has a "notify" event set that notifies that the composite widget’s "input-purpose" property has changed too

Everything works great. I was just wondering if there was an easy way to switch from g_object_notify() to g_object_notify_by_pspec() for the case in point, in order to create a general purpose function that is a bit more optimized (GParamSpec pointers should be a bit faster than strings). But if not, strings will do just fine.

Oh right. But that is accessible only from within the compilation unit that is defining the class itself, isn’t it? Let’s say I want a pointer to GtkTextClass from my own compilation unit: I can’t (unless such class is derivable), right?

No, it’s not: it part of the API, except for final types.

Okay, thank you. I will try to think about the various possibilities then, and in case I will write here again.

Unless you can cache the GParamSpec pointer, there is zero advantage in changing from g_object_notify() to g_object_notify_by_pspec(), because the former literally does what you’re doing: It looks the pspec up by name and then calls g_object_notify_by_pspec() on it.

I suspect you might be prematurely optimising things here. Unless these properties are changing many multiple times per second, the performance difference between g_object_notify() and g_object_notify_by_pspec() is unmeasurable.

I can cache it indeed (that is why I wanted it – without it I would cache a strdup-ed string, not very clever). But I have just solved thanks to this solution suggested by @ebassi, used in conjunction with g_object_class_find_property():

As I said, I am creating a general-purpose “echo-notify” function that allows to propagate many notifications at once (i.e. varargs), so it would be placed outside of the compilation units that define the various classes.

Everything works perfectly as planned now. Thank you both for your help!

Hi,

Sorry to bother again. At the documentation of g_object_class_find_property() I read:

Return value

Type: GParamSpec

The GParamSpec for the property, or NULL if the class doesn’t have a property of that name.

The data is owned by the instance

Does that mean that eventually I will have to launch g_param_spec_unref() at some point? Or to say it differently: does g_object_class_find_property() call g_param_spec_ref() before returning me the GParamSpec?

“The data is owned by the instance” means that you don’t need to release a reference to the GParamSpec.

Ok, thank you, Emmanuele. I find it a bit confusing here because with the “instance” the documentation here means a “class”.

Yes, I’ll have to fix that particular case.

1 Like

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