GNOME Bugzilla – Bug 363228
Reflection in glib 3.0
Last modified: 2015-02-07 17:03:20 UTC
It would be nice if you'd add reflection support in glib for functions. Registred would be: - Public functions - Virtual fuctions - Abstract virtual functions for example: foo-bar.h(fragment): struct _FooBarClass { FooBarParentClass parent; void (*virtual_function)(FooBar *self) }; void foo_bar_some_function(FooBar *); void foo_bar_some_virtual_function(FooBar *bar); GType foo_bar_get_type (void) { static GType foo_bar_type = 0; if (!foo_bar_type) { static GTypeInfo info = { sizeof (FooBarClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) class_init, NULL, NULL, sizeof (FooBar), 0, (GInstanceInitFunc) init }; foo_bar_type = g_type_register_static (FOO_TYPE_BAR, "FooBar", &info, 0); /* Function registration could be also in class init */ g_type_register_function(foo_bar_type, &foo_bar_some_function, "foo_bar_some_function", foo_bar_type, NULL); g_type_register_function(foo_bar_type, &foo_bar_some_virtual_function, "foo_bar_some_virtual_function", foo_bar_type, NULL); g_type_register_virtual_function(foo_bar_type, sizeof(FooBarParentClass), /* Offset */ "virtual_function", foo_bar_type, NULL); g_type_overload_function(foo_bar_type, FOO_BAR_PARENT_TYPE, "abstract_function", &abstract_function); } return foo_bar_type; } Why: - Class which has not overloaded abstract methods should be abstract (if not it should be some error) - It could make simpler looking throught object tree Optimalisations: - As in cast checking it should be possiblt to switch it off Regards
I'm actually writing support for this at the moment as part of dbus-glib. Currently I'll prototype it and get it working there first, and then propose it for inclusion in dbus-glib. You can follow the development in the introspection branch in http://gitweb.freedesktop.org/?p=users/robtaylor/dbus-glib.git;a=summary
There's a module in CVS where Matthias started on this also, if you didn't see it
Yeah, I've looked it through thoroughly, unfortunately it doesn't really solve the problem in a way that's useful for the way we want to go with dbus-glib - we want the method introspection to be gtype based and installed in class_init like signals and properties, rather than a binary blob. I've referenced some of his g_invoke implementation though as I'm making use of FFI
I'd be pretty worried about the performance and convenience of that approach, that's why dbus-glib at least originally had its own binary blob (not sure where you've gone with this). Two advantages to the binary "type lib" are: - it can be one read-only shared library symbol, which is way way cheaper than a runtime-malloc'd data structure - it can be generated from an "idl" file or by scanning magic comments or something, rather than by manually typing a bunch of registration functions in class_init You may be right about the issues, but I'd encourage you to write things up and send to gtk-devel-list if you have time, because a dedicated introspection system for dbus-glib is bad (and is one reason I think it's tough to finalize dbus-glib - ultimately it should just use GLib's standard introspection, but GLib's standard introspection doesn't exist yet). By writing up and keeping gtk-devel-list regularly updated it greatly increases the chances of getting a patch into GLib proper, which should really improve dbus-glib. And whatever the issues with a binary type lib maybe people have ideas to solve those while preserving the advantages.
I agree having a dedicated introspection system for dbus-glib would be bad. My current approach is to get it all working in a development branch of dbus-glib, so I can be sure I've understood the problem correctly and can do at least a pretty optimal implementation, and then take it over to gtk-devel. I think I'll be ready to talk meaningfully about it pretty soon. Having some reference code to hand should make things go a little more smoothly too :) In terms of efficiency, I think I can get it slightly more efficient than signal registration. Noting this here, but I'll bring it to a gtk-devel discussion later: The problem with the static blob approach is that it effectively means you end up defining a new static type system for glib. As dbus-glib already gives you the ability to define implementations of complex types, going that way would with mean having a whole load of (inefficient) machinery to convert between type systems (which'd get pretty complex), or we'd need to rewrite most of it and have different marshalling for signal callbacks than method calls. The static blob approach would also mean being able to (de)marshal user defined structures would get pretty complex too, which is something I'd really like to see.
Signal registration is too inefficient though to register every function in the gtk stack, which is part of the idea here. To avoid different method and signal marshaling, I would suggest that both methods and signals are in the static typelib, and then signals are registered in the GType system in class_init using the typelib. i.e. the manual signal registration calls in class_init could be dropped. dbus-glib could use only the static info. Or we could just suck it up and use two kinds of marshaling in dbus-glib. What are you referring to when you say "ability to define implementations of complex types" ?
"ability to define implementations of complex types" == http://dbus.freedesktop.org/doc/dbus-glib/dbus-glib-Specializable-GType-System.html) I have to admit, I wasn't really thinking of the case of a fully introspectable GTK. I agree this scheme isn't going to be good for that case,we'd be talking around 400K of dirty writable, which isn't great considering we want to reduce gtk's dirty writable usage... However, I also really really don't want to see two quite different type systems in glib, its already confusing enough for most as it is. I have a slightly crazy idea that we might be able to define GTypes statically in read-only data. I'm going to think on this and if that's possible its a way forward to having GType-based introspection in read-only sections. It would also go some way to reducing dirty-writable usage of GTK. However it could mean some pretty nasty ABI exposure :/ What do you reckon? completely insane?
Hmm. My take on the specialized GType like that is that it has a lot of downsides. Perhaps I'll veer a little off-topic for gtk bugzilla here but - I think the right ideal for the dbus-glib bindings is to say "the API for a remote object should not have anything we wouldn't put in a hand-written C API," and I certainly don't think I'd want to program with a struct type like that. Or even a GHashTable is a very strange thing to have in an API, I can't think of any API in the whole GTK stack that takes a hash table. GValue makes few appearances either, outside of object internals and language binding glue. Creating these dbus-glib specific generic data types also has the downside that it's expensive, in principle libdbus makes only one copy into the DBusMessage from the socket, and only one more copy should be needed (from the DBusMessage into an application data structure). Another expense of course is that a GType is never unregistered, and the number of "parameterized" GType ("struct of <parameters>") is theoretically infinite. I think the two good ways of handling a struct would be: 1) iterators. Just wrap DBusMessageIter and apps can traverse the data and convert it into an application data structure. It looks like the specialized GTypes end up looking like this anyway, since it's about the only way to dynamically deal with these types. But there's no reason to first create and convert to a specialized GType if the app is just going to iterate and suck out the data; sucking straight from the DBusMessage would be much simpler and more efficient. 2) CORBA-style where you can define a C struct and the binding knows how to fill it in (unlike solution 1, this does not solve dicts/arrays at the same time) In either of these cases there would basically be a single GType ("DBUS_G_TYPE_STRUCT" or something, or maybe also "DBUS_G_TYPE_DICT" etc.) for passing through the GType system, but a DBusGStruct value would have the signature attached to it (using the dbus type system). Alternatively there could be a DBusGIter that was like DBusMessageIter and could point to multiple types of value. Making this convenient involves special-casing simple cases to make them nice, e.g. you might need a fairly cumbersome API to deal with a fully generic case like a struct with dicts of structs, but as dbus_message_get_args() does, you can special-case an array of int or a struct with only primitive types in it or whatever. Anyhow... getting back to gtk. It seems to me that we could store type names in the static introspection data, then have some kind of static mapping from type names to the corresponding get_type() function, so we would register types as needed when we want to do something dynamic with the static data. In gobject-introspection/metadata-format.txt search for GTypeBlob to see how Matthias had handled it.
I think you've slightly misunderstood the point of the specialized gtypes: in the endgame they should just be a way of recursively describing your own data structures. The current api shouldn't need to be used, except by the bindings and some macros for registering them, hence making demarshalling a one-copy operation. But thats a little off topic for now, as you so rightly say - we should take the discussion to the dbus ml. For glib introspection, I was thinking of something slightly more radical than a static mapping to get_type. I'm thinking its might be plausible to put TypeData- and TypeNode-like structures in the code section, and so skip the whole registration process and the writable memory use, with some module-local initialisation function that registers the type names. Static introspection data could just reference the type-node directly at linktime. The only overhead then of the type would be the quark and somewhere to put qdata (obviously qdata access would be slower). I'm gonna try prototyping this out in a git branch of glib to see how crazy it is...
Ok, attempted - and its crazy... Having thought about this a lot more I can understand where gobject-introspection is coming from, and the metadata blob at least makes sense. I think the way forward is to introduce extra constructs to gtk-doc so that the xml metadata description can be automatically produced, so it becomes just an xml description of the interface described in the documentation/code rather than an IDL. It'd also be useful to introduce fundamental gtypes so theres a 1-1 mapping between gobject-introspection basic types and fundamantal gtypes. We wouldn't actually need different marshalling paths for signals and functions using gobject-introspection, it can all be done in terms of the introspection metadata. Signals receiving structs can use G_TYPE_POINTER, just as they've always done, and the dbus recursive types can be dropped. Sounds right?
random thoughts as I read your comment: - you might do the magic comments separate from gtk-doc comments (there are already some magic comments bindings use for .defs files, I think) - 1-1 mapping from introspection types to fundamental types I don't have a lot of opinion on (not sure of the implications) - G_TYPE_BOXED is often preferred to G_TYPE_POINTER - indeed, signals and functions should be able to use similar marshaler logic
Well. In his last speech (about C++0x) Bjarne Stroustrup said about problems with reflection. May be the data should be autogenerated and put in data secion (or at least to mmaped) to allow applications to share it through. Ie. if data for gtk+ would take 10 kiB and I have 38 application running (get from ps -u xyz | wc -l) it should occupy 10 kiB in memory not 380 kiB. If the metadata was load by mmap it might not occupy memory at all if no program used it. However I don't know how is mmap on Windows.
I forgot to write what he said :( He said about progrem build with and without reflection. Without reflection there was 80% of code and 20% of data and with there was 20% of code and 80% of data.
(In reply to comment #13) > I forgot to write what he said :( > He said about progrem build with and without reflection. Without reflection > there was 80% of code and 20% of data and with there was 20% of code and 80% of > data. do you actually have a link to the origin/article/comment where Bjarne is qouted?
(In reply to comment #14) > (In reply to comment #13) > > I forgot to write what he said :( > > He said about progrem build with and without reflection. Without reflection > > there was 80% of code and 20% of data and with there was 20% of code and 80% of > > data. > > do you actually have a link to the origin/article/comment where Bjarne is > qouted? > No. I have only presentation (whatch out it's nearly 2 h long). Here's the presentation in flash, Xvid, MP4, MPG by HTTP and BitTorrent. http://csclub.uwaterloo.ca/media/C%2B%2B0x%20-%20An%20Overview.html
GObject-Introspection provides this already. I think we can pretty safely close this bug now.
[Mass-moving gobject-introspection tickets to its own Bugzilla product - see bug 708029. Mass-filter your bugmail for this message: introspection20150207 ]