Hacker News new | past | comments | ask | show | jobs | submit login
Gtk-rs: The huge and long awaited release is finally here (gtk-rs.org)
147 points by trextrex on Aug 24, 2017 | hide | past | favorite | 44 comments



From the homepage:

> Rust bindings for GTK+ 3, Cairo, GtkSourceView and other GLib-compatible libraries

http://gtk-rs.org/


Congratulations, keep up the good work!

I noticed there seems to be a webbrowser widget too, which I'll have to play with.

'Added PDF as a target Surface' that sounds very useful too!

I'm just wondering would it be possible to make the gtk widgets copyable, as wouldn't that mean you could remove the clone! macro calls, or am I mistaken there?


How does a pointer-soup toolkit like GTK work with Rust? For example, this code:

    let button = Button::new_with_label("Click me!");
    window.add(&button);
    button.connect_clicked(|_| {
        println!("Clicked!");
    });
We just mutated the button (connect_clicked) while the window holds a reference to it. Isn't that disallowed in Rust? How do the GTK types interoperate with Rust ownership?


In Rust there is this concept called interior mutability. Which allows the user to mutate something through a shared reference (&T).

You might want to say "hold on, how can this be safe?" The trick here is that there are runtime checks to make sure only one reference is used for mutation.

Oh, did you believe all checks needed to make Rust memory safe is done at compile time? Well that's too bad.


Except this isn't guaranteed to be safe, because the implementation [1] just calls GTK in an unsafe block:

    fn add<P: IsA<Widget>>(&self, widget: &P) {
        unsafe {
            ffi::gtk_container_add(self.to_glib_none().0, widget.to_glib_none().0);
        }
    }
Oh, did you believe that Rust always does checks to ensure memory safety? Well that's too bad.

Unsafe blocks are for exactly those situations where the compiler can't prove safety at compile time, giving you an escape hatch to say "this really is safe, I know what I'm doing". There are some runtime-checked abstractions built on this, but they can't help you when interacting with non-Rust code.

[1] https://github.com/gtk-rs/gtk/blob/8949ac0304660f53e1fbe2850...


Gtk-rs owner here: the unsafe block is "simply" because rust considers all FFI calls as unsafe. We strongly rely on GTK's functionalities in order to make its usage safer. After you can always break the world if you want.


So given that this isn't actually safe, you can presumably write some code that has undefined behaviour using this library for us?


Well that's the question, isn't it?

Here's one scenario that might invoke UB: create a top level widget, call destroy() [1] on it, then use the widget.

Does that invoke UB? If not, why not - how does Rust's ownership model interact with the GTK one?

[1] http://gtk-rs.org/docs/gtk/trait.WidgetExt.html#tymethod.des...


I tried to test this by modifying the example on http://gtk-rs.org so that the window would be destroyed immediately after creation. When I ran it under valgrind, there were lots of memory access violations. (Valgrind: "Go fix your program!")

I thought that would settle the matter, but then I ran the unmodified code, and it generated essentially the same error messages. Filing a bug report right now.


Looking at your bug report, the first few errors are in g_object code and have absolutely nothing to do with Rust, let alone gtk-rs. (It is known that jemalloc, Rust's allocator, doesn't play nicely with valgrind, but not even that is in play). Given that the stacks start with dbus, none of these errors are relevant to gtk-rs.


I did not get any similar errors on other GTK apps I tested, so I'm relatively confident that it is at least somewhat related to the way gtk-rs does things. I do not seriously expect any Rust code to directly violate memory safety, but calling C code in GTK incorrectly can still have the same effect.


For those still watching this thread: the memory accesses were correct, valgrind just couldn't handle the jemalloc allocator. Using the system allocator instead, even destroying the window before using it does not lead to invalid accesses.


Isn't it still undefined behaviour to do so, though?


Valgrind doesn't detect anything, so I guess GTK's reference counting does the right thing and doesn't prematurely free data still referenced somewhere else. It just doesn't show a window.


Yes, it's possible to write unsafe code that exhibits undefined behavior in Rust in general (not just through FFI and bindings such as this).


Sure, but this isn't unsafe code. Code using this library isn't written in an unsafe block, right? You just use it like any other Rust library?


It's unsafe to Rust. Rust has defined safety to mean a certain thing. In order to support FFI in general the Rust compiler must assume nothing about the safety guarantees of the other language, and therefore that it should be considered "unsafe" according to Rust.


If you're asking about gtk-rs, yes you use it just like a library. The only reason the unsafe block is there is because it does FFI. The Rust compiler inherently doesn't trust ffi calls. That doesn't mean necessarily that the call is actually unsafe.


If you write code that can be called without 'unsafe' then you are required to make that code safe. Whether you implement it using unsafe underneath is irrelevant.

The unsafe block is there because it does FFI, which hasn't actually been verified to be safe.


You're rephrasing exactly what I said:

> The Rust compiler inherently doesn't trust ffi calls. That doesn't mean necessarily that the call is actually unsafe.


unsafe{} means "hey compiler, you cannot verify but this is safe, but I have." This code should be safe to use, unless the human involved has messed something up, in which case, it's a bug.

It's more that the possibility for UB now exists, than it definitely does.


Maybe unsafe should be called assume_safe or presumably_safe or maybe_unsafe... People easily understand it wrong


We considered many things, but in the end, nothing is perfect.


> Oh, did you believe all checks needed to make Rust memory safe is done at compile time? Well that's too bad.

Actually yes. You can write all the programs you want without runtime borrow checking, but it's inconvenient. Runtime borrow checking happens _only_ when you use cells.


And not even all cells, just RefCell.


Why does cells even exist then?


Hi. Can we take the tone down a notch?

> When disagreeing, please reply to the argument instead of calling names. "That is idiotic; 1 + 1 is 2, not 3" can be shortened to "1 + 1 is 2, not 3."

https://news.ycombinator.com/newsguidelines.html

You didn't call anyone names but the sarcasm and patronizing tone aren't necessary.


Is Gtk bundle into the final executable?


Each example binary is about 3-4 MB when built in release mode and they use the gtk .so files.


So a static build is not possible?


Gtk+ is complex enough that statically linking libgtk3 isn't going to be enough anyway, there's all sorts of extra resources GTK relies upon beyond the .so that it's rather pointless to even try.


How then are people packaging gtk-rs for Windows? Any idea?


I've just used WiX (http://wixtoolset.org/) to bundle GTKs dlls together with my program. I've not investigated statically linking GTK though.


I've used Quod Libet and Meld, both GTK+ 3 apps, on MacOS by downloading .app bundles, so it must be possible, and maybe desirable on non-Linux(/BSD) platforms.


Mac .app bundles are folders, you can have both frameworks and .dylibs inside. Quod Libet, for example, has a whole bin/lib/libexec hierarchy inside its .app with shared Gtk libs, Python, etc.


Ah, of course. I've used "Show Package Contents" enough that I should've realized.


Looking at the change log, I see they generate a lot of code with a custom tool called "gir":

https://github.com/gtk-rs/gir

Is it an acronym for something, or is just someone on the team a closet Invader Zim fan? :)


See https://wiki.gnome.org/Projects/GObjectIntrospection

GIR seems to be the XML format containing GObject introspection data.

For what it is worth, the equivelent haskell library (haskell-gi) is composed of two source code directories: GIR and CodeGen. [0]

[0] https://github.com/haskell-gi/haskell-gi/tree/master/lib/Dat...


Without looking at the code, considering we are talking about GTK, I would guess it's related to "GObject Introspection".


Can we come up with something other than GObject/GTK? :(. I want a cross platform GUI that looks native.


Kudos to the collaborators.

It seems everything these days is going either Rust or Go.


It's just an echo chamber effect. People still use other languages for their daily stuff. It's just that people want to write their hobby projects and new small work stuff in go or rust. Would take some years for main stream adoption that current popular and established languages enjoy. But rust and go have momentum going for them.


I think the difference is that Rust and Go projects seem to be posted to HackerNews (and upvoted!) much more than Python and C++ projects are, despite there being way more of the latter.


> It seems everything these days is going either Rust or Go.

Lots (most?) of things are simply just already built, keep on working and not going anywhere new.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: