5 ms·
I tried this and is awful. GTK and Rust have two very different ways of managing memory and it's painful. Lucky, gtk-rs already helps you with their own types p
by aarroyoc 7y ago
I tried this and is awful. GTK and Rust have two very different ways of managing memory and it's painful. Lucky, gtk-rs already helps you with their own types prepared to be used with Rc but with your custom types you need to define all the garbage collector stuff your yourself which makes the code look very ugly (lots of clone, which aren't really clones).
At the end the result is good, but the code looks awful.
- spystath 7y agoMy experience is kind of similar. Unfortunately the way Rust interacts with memory is quite different from how Gtk does (and most GUI tool-kits to be fair). The end result is a kind-of awkward battle between the Rust borrow checker and the internal memory handling of Gtk+ leading to loads of Rc<RefCell<T>>. This makes also quite hard to implement custom Widgets in an intuitive way. In Python or C++ you would subclass the generic "Widget" class and start implementing the bits you need. With Rust things are slightly complicated; you can't just implement the IsA<Widget> trait and call it a day; at least not a straightforward way. Hopefully gnome-class [0] will probably solve this problem eventually. That being said it's been a while since I've used gtk-rs so it is entirely possible things have changed. I'd love to be corrected if that's the case :) [0] https://gitlab.gnome.org/federico/gnome-class/ https://gitlab.gnome.org/federico/gnome-class/
- duguxu 7y agoI have kept an eye on this for a long time. Is there any design pattern with Rust style (no unsafe and not ugly from Rust community's perspective) that proved in prototype to be able to achieve the same scaling of performance and memory usage as native C/C++ GUI framework with more complicated interface (e.g. Office)? Could this be an inherent limit of Rust because of the memory safety principle?
- pcwalton 7y agoI would like to see an ECS style UI design in Rust that represents widgets as IDs, to allow arbitrary object graphs without interior mutability. I don't see a reason why this would be incompatible with GTK, but we won't know until we try. It might work out really well. It also might be that Rust is not the right language to write high level UI logic in at this time, and a GC'd language would be more appropriate. That's fine too. One of the strengths of Rust is its interoperability with other languages. C and C++ are certainly not the right languages to implement high level UI logic in, for example.
- duguxu 7y agoI agree with you. From my point of view, the advantage of C/C++ for UI is not about high level logic, but complicated custom widget with lots of low level functions and good performance. C/C++ is not good for a weather app, but almost the only choice for the canvas of Photoshop or the waveform of Audition, and it seems like no one else considers seriously challenging this. I am confident that given enough time, Rust will be adopted for social app or game GUI. But I don’t know if this would prevent Rust from writing practical large productivity software.
- pcwalton 7y agoI am very much not saying that C++ is the answer for large-scale productivity software. In fact, I'm saying the opposite. Let me be clear: Given the choice between Rust or C++ for writing Photoshop, I will pick Rust every time.
- duguxu 7y agoI am not saying that C++ is the answer for large-scale productivity software, but C++ is the answer for the complicated widgets used there. I would prefer Rust for the main framework of photoshop too, but I am not sure whether there is an elegant way writing the canvas widget.
- pjmlp 7y agoYet, although Microsoft security now advises for C#, Rust and constrained C++, they went ahead and are using C++ for React Native and WinUI 3.0, removing the dependecy on .NET Native. Apparently because that is the only way to sell MFC/ATL holdouts to WinUI, and allow WinUI to be called from classical Win32 without too much overhead, and also because .NET Native ideas will be migrated to .NET 5.
- barrkel 7y agoDelphi and C++ Builder did well enough with high level UI logic. C++'s problem is that the path of righteousness is too narrow, but with heavy cultural idioms and norms, you can keep a lot of the people safely hemmed in, while retaining all the escape hatches.
- nonbirithm 7y agoI was wondering something similar. This reminds me of the time a few months ago where someone gave up on writing a pure Rust binding to Wayland because the memory model in Wayland doesn't play well with the borrow checker[0]. It seems that the problem is you can write any arbitrary way of manually managing memory in C that doesn't necessarily have a complement in entirely safe Rust. I'm not really sure this can be reconciled with any arbitrary C library. One of the benefits I see from Rust is the ability to be unable to do unsafe things without explicitly stating you know what you're doing, thus preventing various classes of errors. But it feels like if the ownership model just doesn't fit with Rust's model that allows those guarantees to be made in the first place, it won't work. You can't write just anything in safe Rust without limiting the things you can do, but C libraries don't have such limits. It might take creating new ways of representing GUI objects before the best model for that problem arises for Rust. I don't think libraries like GTK were designed with the lessons in safe memory management Rust learned from years after the fact in mind. [0] http://way-cooler.org/blog/2019/04/29/rewriting-way-cooler-in-c.html http://way-cooler.org/blog/2019/04/29/rewriting-way-cooler-i...
- pjmlp 7y agoAgreed, I went through the same pain when I ported by dummy Gtkmm from an old article into Gtk-rs, Rc<RefCell<T>> everywhere. This is such a pain that even Gtk-rs samples have macros to work around cloning widget state into callbacks. From my point of view language ergonomics still need to improve for Rust to actually be a candidate for GUI development, versus what the GC based languages (RC and tracing GC) offer out of the box with their UI kits. Unless one envisions it just to take C++'s role of visualization layer and integration with graphics drivers.
- ptx 7y agoIn SWT, even though Java is garbage-collected, resources must be explicitly disposed[1]. Often they are bound to the lifetime of a parent object and disposed when that parent is disposed. This seems to work OK in SWT, so what's the problem in GTK/Rust? Are there some particular categories of objects that don't fit into that hierarchical model and need to be handled with a GC? (Those objects would presumably be regular Java objects in an SWT app and handled by Java's GC.) [1] https://www.eclipse.org/articles/swt-design-2/swt-design-2.html https://www.eclipse.org/articles/swt-design-2/swt-design-2.h...
- pjmlp 7y agoThe problem is called borrow checker, and that while the Rust team already has done lots of improvements with NLL, the use of widget data in callbacks remains a pain point. "Appendix: What the proposal won’t fix" http://smallcultfollowing.com/babysteps/blog/2017/07/11/non-lexical-lifetimes-draft-rfc-and-prototype-available/ http://smallcultfollowing.com/babysteps/blog/2017/07/11/non-... So one could say, it is a case of holding it wrong, and a Rust UI toolkit needs to be written from scratch. Which might be ok, but it does require some support for market adoption. Having said this, Gtk-rs now has some help in the form of relm, exactly to overcome this issue. https://github.com/antoyo/relm https://github.com/antoyo/relm
- barrkel 7y agoOne way to handle GUI componentry is to separate out the notions of ownership, parentage and reference. Ownership defines who frees who. Parentage defines control nesting. References should to be handled via an indirection (e.g. names) and a protocol so that referees get notified when referents die. The indirection means that components get wired up in a late bound fashion; and the late binding means the gubbins for a protocol can be in place by then. This stuff was figured out reasonably well with Delphi's VCL.