GNOME Bugzilla – Bug 646080
c:type is missing for parameters on glib:signal entries in the gir
Last modified: 2018-02-08 12:04:08 UTC
Gir files with repository version 1.1 included c:type definitions for all properties, fields, method parameters and glib:signal parameters. Files with version 1.2 are missing the c:type on signals. This attribute is very important for bindings to know exactly what the underlying type is, the name is not enough (ambiguous, incomplete). Gtk-2.0.gir: <glib:signal name="connect-proxy" version="2.4"> <return-value transfer-ownership="full"> <type name="none" c:type="void"/> </return-value> <parameters> <parameter name="action" transfer-ownership="none"> <type name="Action" c:type="GtkAction"/> </parameter> Gtk-3.0.gir: <glib:signal name="connect-proxy" version="2.4"> <return-value transfer-ownership="none"> <type name="none"/> </return-value> <parameters> <parameter name="action" transfer-ownership="none"> <type name="Action"/> </parameter>
Turns out this regression is also affecting properties.
Very important indeed: omitting the c:type attribute causes an issue for the GIRepository C interface, in particular g_type_info_is_pointer is returning false for interface types (of signal parameter/return values and property values) when it should return true. This happens because e.g. <type name="Display"/> is present in the GIR file instead of <type name="Display" c:type="GdkDisplay*"/> With the first, there is no indication that the type is a pointer.
For the semantics and necessity of g_type_info_is_pointer(), see bug 561099. Generally, you should rely on it as little as possible. In this case, just assume that interface types (except enums and flags) are their "natural" C type, which is pointers. The reason the c:type is omitted for signal parameters is that it doesn't exist in the C source code. In GObject signals are defined using GTypes. Now...we could just make one up (and I think this is what the old code did, but it'd be conceptually wrong). Bottom line is to change your binding code to assume "natural" types. This isn't really rigorously defined, but look at gjs for example of how it's done: $ git grep is_pointer gi/arg.c: needs_release = g_type_info_is_pointer(type_info); gi/arg.c: !g_type_info_is_pointer(param_info)); gi/boxed.c: if (!g_type_info_is_pointer (type_info) && gi/boxed.c: if (!g_type_info_is_pointer (type_info) && gi/boxed.c: if (g_type_info_is_pointer(type_info)) { $
(In reply to comment #2) > Very important indeed: omitting the c:type attribute causes an issue for the > GIRepository C interface, in particular g_type_info_is_pointer is returning > false for interface types (of signal parameter/return values and property > values) when it should return true. This happens because e.g. > > <type name="Display"/> > > is present in the GIR file instead of > > <type name="Display" c:type="GdkDisplay*"/> > > With the first, there is no indication that the type is a pointer. From Gdk-3.0.gir: <class name="Display" c:symbol-prefix="display" c:type="GdkDisplay" parent="GObject.Object" glib:type-name="GdkDisplay" glib:get-type="gdk_display_get_type"> "class" means that it's always a pointer. You cannot allocate a GType instance on the heap.
Er, you cannot allocate a GType instance on the stack.
(In reply to comment #3) > For the semantics and necessity of g_type_info_is_pointer(), see bug 561099. > Generally, you should rely on it as little as possible. As I couldn't find any information on parameter passing conventions and there seemed to be considerable scope for variation, I was using g_type_info_is_pointer to cross-check assumptions that I was making on how particular types were passed. It wasn't necessary. If, by design, there is no dependence on c:type annotations to determine how data is passed around, that is good. > In this case, just > assume that interface types (except enums and flags) are their "natural" C > type, which is pointers. Ok, but to work out the C representation of parameters, there is a little more to it: e.g. an out (or inout) parameter has an extra level of indirection. Also, we know that a struct interface type uses a pointer, so an out parameter with a struct interface type has two levels of indirection, e.g. parameters path and cell of gtk_icon_view_get_cursor. But that is not always the case, e.g. parameter iter of gtk_text_buffer_get_end_iter has only one level of indirection: it depends on whether a struct parameter is caller-allocates. I don't see this as an issue. However, working out the C representation from introspection data could usefully be documented. > The reason the c:type is omitted for signal parameters is that it doesn't exist > in the C source code. In GObject signals are defined using GTypes. Now...we > could just make one up (and I think this is what the old code did, but it'd be > conceptually wrong). Yes, that seems wrong. (But then is it wrong that the reference documentation has C function prototypes for signals?)
(In reply to comment #4) > "class" means that it's always a pointer. So perhaps g_type_info_is_pointer (or the typelib data that is uses) could build in that logic? But it sounds like that function is on the way out...
(In reply to comment #7) > > In this case, just > > assume that interface types (except enums and flags) are their "natural" C > > type, which is pointers. > > Ok, but to work out the C representation of parameters, there is a little more > to it: e.g. an out (or inout) parameter has an extra level of indirection. > Also, we know that a struct interface type uses a pointer, so an out parameter > with a struct interface type has two levels of indirection, e.g. parameters > path and cell of gtk_icon_view_get_cursor. But that is not always the case, > e.g. parameter iter of gtk_text_buffer_get_end_iter has only one level of > indirection: it depends on whether a struct parameter is caller-allocates. It's a bit annoying, yes. But really, it's the other way around: we have all these APIs using different conventions, and we need to find a common set of semantics for them. > I don't see this as an issue. However, working out the C representation from > introspection data could usefully be documented. Yeah, that could be fine. > Yes, that seems wrong. (But then is it wrong that the reference documentation > has C function prototypes for signals?) I do not understand what you mean by this.
(In reply to comment #8) > > Yes, that seems wrong. (But then is it wrong that the reference documentation > > has C function prototypes for signals?) > > I do not understand what you mean by this. I am just observing that the 'recovering' of C types from GTypes has been done for signals in the reference documentation: the C function prototypes mention C types, e.g. void user_function (GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, gpointer user_data) : Run Last I find a clear statement of the C types like this very useful when interfacing another language to the C library. Perhaps it is conceptually wrong to define/document the signal interface using C types that do not occur in the library source code. However, given that many FFIs are documented in terms of calling C, I don't think it would be good to lose sight of the C types.
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]
Just recording here that C types really shouldn't be depended on. It gets worse with arrays. For example, consider Pango.LayoutLine.get_x_ranges: <parameter name="ranges" direction="out" caller-allocates="0" transfer-ownership="full"> <doc xml:space="preserve"> ...</doc> <array length="3" zero-terminated="0" c:type="int**"> <type name="gint" c:type="int*"/> <-- !!!! </array> </parameter> There is a similar issue for: Gdk.Keymap.get_entries_for_keycode, arg keyvals Gdk.property_get, arg data Gtk.IconSet.get_sizes, arg sizes Even weirder is Gtk.IconTheme.choose_icon: <parameter name="icon_names" transfer-ownership="none"> <doc xml:space="preserve">%NULL-terminated array of icon names to lookup</doc> <array c:type="gchar*"> <-- !!!! <type name="utf8" c:type="gchar"/> <-- !!!! </array> </parameter> Even just using the C type to determine whether it is a pointer is broken.
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gobject-introspection/issues/47.