[Solved] Gtk-rs, ownership and callbacks



so as a kind of weekend project to see how Rust would handle GUI coding, given the recent thread on GUI support, I have decided to port an very old Gnomemm application I have done in the past into modern shinny Rust and Gtk-rs.

The Gtk-rs tutorials have everything inside main, which while great for learning, aren’t that nice for doing actuall applications.

So after having my application fully running inside main, I had the idea of using a struct with some methods instead. Here is when my ownership issues started.

I have solved all of the up to one regarding callbacks, which no matter how I search the Internet, or workarounds that throw at the compiler, nothing seems to make it happy.

Basically I have such a structure

impl GWCApp {
   fn on_menu_open(&self) {

   fn init_menus (&self) -> MenuBar {
        file_item.connect_activate( |_| {


The compiler isn’t happy with my self.on_menu_open() call, although from my point of view, it being a method on self will clearly have the same lifetime as the application.

The full code is at https://github.com/pjmlp/gwc-rs/blob/master/src/main.rs.

So I am kind of lost out to sort this out, even with my modern C++ knowledge, I don’t know where more to dig in what concerns Rust lifetimes.

Can someone just let me know what I am kind of missing?



I’m guessing the issue is that the compiler can’t be sure that GWCApp outlives the MenuBar that’s returned and contains a reference to the app.

One option might be to put the fields of GWCApp inside a Rc<RefCell<...>> so that you avoid lifetimes altogether in this scenario.


The docs for connect_activate state that the callback must have a static lifetime. Maybe you’ll need to stash your GWCApp in a lazy_static initializer.


Thanks for the replies.

After going at it for a few more hours, I have decided to throw away the struct, keep all the code in main and sprinkle a few Rc<RefCell<<>>>() as function parameters, while trying to delve into the Gtk-rs examples.


Note that all Gtk objects are already reference counted, so when it’s just about them, one can just use .clone() and let the closure capture the new handle by value.


No, it was a method being called from a closure not allowing to keep a reference to self, as you can see on the example, init_menus() and on_menu_open() are methods on the same structure.

Something that in C++ I would have easily sorted out with enable_shared_from_this or using closure capture list.


As @G2P pointed out, that API requires that the closure you pass holds no references (or 'static references). As mentioned, you should be able to keep your GWCApp (rather than a giant main) but use Rc<RefCell<...>> for its fields. Then you’d pass (move, to be precise) a clone of the Rc to that closure, and that should work.


Thanks once more for the help, but it is too much work for what was a simple weekend project to test waters regarding the state of affairs of doing GUI development with Rust.

I really don’t understand how you would do Rc<RefCell<<…>>> for a method reference, not fields.

So the code is reverted back and it is working as before my GWCApp attempt.


You wouldn’t use a self reference in the function; that reference appears to only be needed to get access to the fields. If you pass the fields directly (via the Rc<...>), then you don’t need &selfand therefore sidestep the lifetimes.


Still want I want is to call a method from the callback, regardless of what that method might eventually be doing.

If for sidestepping the lifetimes I need to pass the fields around, then there is no value in having a struct with methods, instead of a few global functions.

Hence why I reverted everything back to a state I knew things were working properly

Thanks again for the support, maybe I just need to spend more time doing lifetime related exercises before delving into these kind of ideas, because right now I still don’t get it why it doesn’t work for methods.


Usually you need to wrap your stuff. Like so:

struct GWCAppWrapper {
  app: Arc<Mutex<GWCAPP>> // mutex if multithreading
impl GWCAppWrapper {
   fn init_menus (&self) -> MenuBar {
        let app = self.app.clone();
        file_item.connect_activate( move |_| {


Thanks for the tip, I will have another look at it.


Just to update, I decided to have another go at it, and managed to somehow get the data into my GWApp struct.

As solution I made the member data into Rc ones and used static members for the callbacks.

For anyone that might face a similar problem, just check the github repository.

Thanks again for the support.