On Fri, 2017-09-01 at 20:06 -0500, Federico Mena Quintero wrote:
I'm not very happy with the code organization yet, any suggestions let me know :) It's all feeling mashed together, the actual safe implementations of the stuff are mixed with the boilerplate.Although I haven't read through the code in detail, it's comforting that the structure is very familiar from a C GObject perspective.
Yeah, it's basically C in slightly different syntax. Not very rusty
I do like how Niko added some "paranoid" features in gnome-class, to do things like making some structs uninstantiable if they are implementation details (e.g. you couldn't create a FooPrivate on your own; you have to get it from the get_private() method). Fortunately this is just boilerplate in the code generator, and can be easily added to your code.
Ah thanks for the reminder, I wanted to copy that part over indeed :)
- Signal "incremented" on Foo - Normal "number" GObject property on BarI see you have a Vec<signal_ids> inside the class private, indexed by an enum. What I was putting in gnome-class was "invisible" fields in the class struct, sort of like FooClass.clicked_signal_id: u32. They would just take up space in the class struct; the corresponding C headers would just have "dummy" fields for them. The Rust code won't have to deal with signal ids, anyway, since all the emit_foo_signal() methods are auto-generated, anyway... but for the implementation that the code generator emits, do you see any advantages of one scheme over the other?
By having it in the class struct, you have something in the class struct that takes up space there (and all subclasses get it too in their class struct). And it's something that is "useless" as part of the API but still there. It just seems ugly to me. Same thing with the param specs for properties btw, and the parent class' class struct. As a static global variable it is completely hidden away from the outside and just an implementation detail. Into the class struct I would only really put vfuncs and public class fields. You could also put it in class private data (g_type_add_class_private()) but that would still have to be stored somewhere as retrieving it all the time is not very cheap IIRC. And there seems no advantage over just having it as a static global variable somewhere.
Things to come: - Some GObject interfaceYes, please! I'm thinking that right now we have gobject_gen! { class Foo: Parent { ... } } should we also allow "interface" as well as "class" in there?
Definetely! And similar to traits, you can have default implementations for the interface methods or leave them unimplemented.
gobject_gen! { interface BarIface { fn oink(&self, ...) -> i32; fn moo(&self, ...); } } (Uh, can one derive a GTypeInterface from another one, sort of like dependent traits? I don't see it done anywhere in GTK+...)
Not really "inherit", but you can require (prerequisites) implementors of the the interface to implement other interfaces are derive from a specific class. This allows the interface implementation to use the API of those other interfaces/classes. See g_type_interface_add_prerequisite().
- Action signalI looked briefly through the gobject source code and I *think* these are just a flag? There's no other distinction from normal signals, apart from the convention of allowing them to be emitted from outside the object's implementation...
Yes, the only difference is that you must have a class handler for the interface (which should be optional in the code generator for normal signals btw). And the invocation is "special" as it goes via the name of the signal instead of the signal ID (as the signal ID is hidden away and can only be queried externally via g_signal_query()), or some emitter function (e.g. gtk_button_clicked()).
- Refcounted and copying boxed typeBeing able to declare our own, public, #[repr(C)] boxed types would be awesome. And simple enums.
They can also be without #[repr(C)] if you make them opaque in the C headers, and then also non-C-style enums can be supported.
(Are GTypeModules too exotic to be worth considering right now?)
Next step IMHO, also not really difficult. The other parts require more thinking :) BTW, one thing that might not have been obvious is that in the "safe" implementation code you never have the normal C struct as an argument but always the gtk-rs-style wrapper that provides safe API for everything, and the private implementation struct. And all the translations back and forth is done via the gtk-rs infrastructure (except where it's missing and there is a FIXME comment). IMHO once gnome-class is finished, it would be a good fit to move this into glib-rs directly.
Attachment:
signature.asc
Description: This is a digitally signed message part