G_param_spec_flags(): How to declare a flags type?

I have an object property for which I am currently using g_param_spec_uint(), but I should be using g_param_spec_flags(), because it can actually contain only custom flags.

However g_param_spec_flags() asks me to specify a GType, which I have no idea where to get from. I guess I have to register my flags somewhere, but I don’t know where.

How does the whole machinery work? Is there a GLib tutorial somewhere that explains how to create from scratch a property that contains flags?

Use G_DEFINE_FLAGS_TYPE or the glib-mkenums utility.

Thank you, Emmanuele. It works if I put the macro in my compilation unit, however it does not work if I put the macro in the header.

As I said, I never registered custom types, so I have no idea about the machinery. What if two different compilation units need to use the same GType? Do I have to copy and paste G_DEFINE_FLAGS_TYPE in every compilation unit that uses those flags? Is there not a way to put the whole thing inside a common header?

Why would you put it in the header? G_DEFINE_FLAGS_TYPE works exactly like G_DEFINE_TYPE: you use it to define a flags type.

Then I strongly suggest you start reading the GObject/GType documentation before you ask for help, so we don’t have to either play a game of 20 questions, or talk past each other.

The typedef enum goes into the header, as well as the get_type function declaration and the TYPE macro that maps to the get_type function.

I really wanted to. I am usually an avid reader of the documentation. But concerning how to register a GType I could not find much. My first question asked for a tutorial to read.

So, imagine foo.c, which implements an object called MyFoo, that declares a bitmask property whose type is MyCustomFlags. If I put G_DEFINE_FLAGS_TYPE inside foo.c everything works fine. But now there is bar.c, which implements another object called MyBar, that also declares a bitmask property whose type is MyCustomFlags. How does the latter know about the GType if no header mentions it?

1 Like

To be fair, the example in the docs for G_DEFINE_FLAGS_TYPE could definitely be a bit more expansive, and give code snippets for the C file and the header file.

There is no tutorial on how to register a flags type, which is what you asked; I assumed you were at least in passing familiar with GObject and the type system, though, since you talked about deriving types and adding properties.

The GObject tutorial and the type system concepts are required reading.

The same way any type knows about another type: through a get_type function (and its corresponding macro) in an header that gets included in both foo.c and bar.c.

So:

typedef enum {
  MY_CUSTOM_FLAGS_DEFAULT = 0,
  MY_CUSTOM_FLAGS_VALUE1 = 1 << 0,
  MY_CUSTOM_FLAGS_VALUE2 = 1 << 1
} MyCustomFlags;

#define MY_TYPE_CUSTOM_FLAGS (my_custom_flags_get_type())

GType my_custom_flags_get_type (void) G_GNUC_CONST;

The G_DEFINE_FLAGS_TYPE macro will the define the my_custom_flags_get_type() function that you declared in the header.

I believe I am familiar with GObject, at least most of its parts. But GTypes are something I never had to actively use, so until now for me they could be anything, they could be integers, they could be structs, etc., because I always used them passively, only when I was asked to pass a GType obtained from somewhere else.

However I see now that I had missed this from your previous message,

which makes everything clear (thank you).

So GTypes are objects too? Or are they something a bit more primitive than objects upon which objects are built?

Perfect. Everything is crystal clear.

A GType is just a number which identifies a type registration in a runtime type store (which is maintained by libgobject).

Each GObject class has a unique GType, but each GType is not necessarily a class. GTypes are also used to identify flag types, boxed types, enums, GTypeInstances (which GObjects are a subtype of), etc.

It’s a runtime implementation of a Java-style type system.

1 Like

Thank you. Silly me before for asking if they are objects, I should have remembered that they are always passed by value (GType and never GType *). As I said, this is something I never had to deal with so far.

Yes, I had a glimpse of what they do, but the exact machinery was completely obscure to me.

I have another question. Actually two. What are the advantages of installing a property via g_param_spec_flags() compared to installing it via g_param_spec_uint()? And more in general, what are the advantages of having a GType for flags instead of having a simple enum?

Type safety and introspection. In most languages other than C, most things are not ints, so we need to expose more type information to them.

All clear. Thank you.

1 Like

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