glib_macros

Macro clone

Source
clone!() { /* proc-macro */ }
Expand description

Macro for passing variables as strong or weak references into a closure.

This macro can be useful in combination with closures, e.g. signal handlers, to reduce the boilerplate required for passing strong or weak references into the closure. It will automatically create the new reference and pass it with the same name into the closure.

If upgrading the weak reference to a strong reference inside the closure is failing, the closure is immediately returning an optional default return value. If none is provided, () is returned.

⚠️ IMPORTANT ⚠️

glib needs to be in scope, so unless it’s one of the direct crate dependencies, you need to import it because clone! is using it. For example:

use gtk::glib;

§Debugging

In case something goes wrong inside the clone! macro, we use the g_debug macro. Meaning that if you want to see these debug messages, you’ll have to set the G_MESSAGES_DEBUG environment variable when running your code (either in the code directly or when running the binary) to either “all” or CLONE_MACRO_LOG_DOMAIN:

use glib::CLONE_MACRO_LOG_DOMAIN;

std::env::set_var("G_MESSAGES_DEBUG", CLONE_MACRO_LOG_DOMAIN);
std::env::set_var("G_MESSAGES_DEBUG", "all");

Or:

$ G_MESSAGES_DEBUG=all ./binary

§Passing a strong reference

use glib;
use glib_macros::clone;
use std::rc::Rc;

let v = Rc::new(1);
let closure = clone!(
    #[strong] v,
    move |x| {
        println!("v: {}, x: {}", v, x);
    },
);

closure(2);

§Passing a weak reference

use glib;
use glib_macros::clone;
use std::rc::Rc;

let u = Rc::new(2);
let closure = clone!(
    #[weak]
    u,
    move |x| {
        println!("u: {}, x: {}", u, x);
    },
);

closure(3);
§Allowing a nullable weak reference

In some cases, even if the weak references can’t be retrieved, you might want to still have your closure called. In this case, you need to use #[weak_allow_none] instead of #[weak]:

use glib;
use glib_macros::clone;
use std::rc::Rc;

let closure = {
    // This `Rc` won't be available in the closure because it's dropped at the end of the
    // current block
    let u = Rc::new(2);
    clone!(
        #[weak_allow_none]
        u,
        move |x| {
            // We need to use a Debug print for `u` because it'll be an `Option`.
            println!("u: {:?}, x: {}", u, x);
            true
        },
    )
};

assert_eq!(closure(3), true);

§Creating owned values from references (ToOwned)

use glib;
use glib_macros::clone;

let v = "123";
let closure = clone!(
    #[to_owned] v,
    move |x| {
        // v is passed as `String` here
        println!("v: {}, x: {}", v, x);
    },
);

closure(2);

§Renaming variables

use glib;
use glib_macros::clone;
use std::rc::Rc;

let v = Rc::new(1);
let u = Rc::new(2);
let closure = clone!(
    #[strong(rename_to = y)]
    v,
    #[weak] u,
    move |x| {
        println!("v as y: {}, u: {}, x: {}", y, u, x);
    },
);

closure(3);

§Providing a return value if upgrading a weak reference fails

By default, () is returned if upgrading a weak reference fails. This behaviour can be adjusted in two different ways:

Either by providing the value yourself using one of

  • #[upgrade_or]: Requires an expression that returns a Copy value of the expected return type,
  • #[upgrade_or_else]: Requires a closure that returns a value of the expected return type,
  • #[upgrade_or_default]: Requires that the return type implements Default and returns that.
use glib;
use glib_macros::clone;
use std::rc::Rc;

let v = Rc::new(1);
let closure = clone!(
    #[weak] v,
    #[upgrade_or]
    false,
    move |x| {
        println!("v: {}, x: {}", v, x);
        true
    },
);

// Drop value so that the weak reference can't be upgraded.
drop(v);

assert_eq!(closure(2), false);

Or by using #[upgrade_or_panic]: If the value fails to get upgraded, it’ll panic.

let closure = clone!(
    #[weak] v,
    #[upgrade_or_panic]
    move |x| {
        println!("v: {}, x: {}", v, x);
        true
    },
);

§Errors

Here is a list of errors you might encounter:

Missing #[weak] or #[strong]:

let v = Rc::new(1);

let closure = clone!(
    v,
    move |x| println!("v: {}, x: {}", v, x),
);

Passing self as an argument:

#[derive(Debug)]
struct Foo;

impl Foo {
    fn foo(&self) {
        let closure = clone!(
            #[strong] self,
            move |x| {
                println!("self: {:?}", self);
            },
        );
    }
}

If you want to use self directly, you’ll need to rename it:

#[derive(Debug)]
struct Foo;

impl Foo {
    fn foo(&self) {
        let closure = clone!(
            #[strong(rename_to = this)]
            self,
            move |x| {
                println!("self: {:?}", this);
            },
        );
    }
}

Passing fields directly

#[derive(Debug)]
struct Foo {
    v: Rc<usize>,
}

impl Foo {
    fn foo(&self) {
        let closure = clone!(
            #[strong] self.v,
            move |x| {
                println!("self.v: {:?}", v);
            },
        );
    }
}

You can do it by renaming it:

impl Foo {
    fn foo(&self) {
        let closure = clone!(
            #[strong(rename_to = v)]
            self.v,
            move |x| {
                println!("self.v: {}", v);
            },
        );
    }
}