You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust GTK程序中按键处理器编译失败问题求助

Rust GTK程序中按键处理器编译失败问题求助

我遇到了一个有点棘手的编译错误,虽然感觉应该是个小问题,但就是找不到症结所在。先贴一下我的代码:

let key_handler = gtk::EventControllerKey::new();

controller.obj().add_controller(&key_handler);

key_handler.connect_key_pressed(clone!(@weak controller => move |_ctlr, key, _code, state| {
    controller.keyboard_input(key, state);
    gtk::Inhibit(false)
}));

这段代码编译时抛出了如下错误:

error[E0069]: return; in a function whose return type is not ()

--> src/controller/imp.rs:80:45

|
80 | key_handler.connect_key_pressed(clone!(@weak controller => move |_ctlr, key, _code, state| {
| ________________________________^
81 | | controller.keyboard_input(key, state);
82 | | gtk::Inhibit(false)
83 | | }
84 | | )
| |
^ return type is not ()

= note: this error originates in the macro clone (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try rustc --explain E0069.

我怀疑问题出在clone!宏的展开上,但不太确定。有没有简单的修复方法?或者我是不是用错了clone!?就在这段代码上方,我有一段类似的代码却能正常编译:

controller.start_buttonx.connect_clicked(clone!(@weak controller => move |xx| BOARDS[1].emit_by_name::<()>("test-signal", &[&x])));

问题分析

其实这个问题的根源在于clone!宏的行为差异:你上面的connect_clicked闭包返回类型是(),而connect_key_pressed的闭包需要返回gtk::Inhibit类型。

当你用@weak修饰变量时,clone!宏会自动生成代码检查弱引用是否能成功升级为强引用。如果升级失败,宏默认会插入return;语句——这个语句在返回()的闭包里没问题,但在需要返回gtk::Inhibit的闭包里,就会因为返回类型不匹配抛出E0069错误。

而你上面的connect_clicked闭包刚好返回(),所以默认的return;完全符合要求,自然不会报错。

修复方案

你只需要在clone!宏里明确指定弱引用升级失败时的返回值,让它和闭包要求的返回类型一致即可。有两种方式可以实现:

方式一:手动处理弱引用升级

直接不用clone!的自动处理,自己写升级逻辑,更直观:

key_handler.connect_key_pressed(move |_ctlr, key, _code, state| {
    let Some(controller) = controller.upgrade() else {
        return gtk::Inhibit(false);
    };
    controller.keyboard_input(key, state);
    gtk::Inhibit(false)
});

方式二:用clone!的@default语法指定返回值

利用clone!宏的扩展语法,指定弱引用失效时的返回行为:

key_handler.connect_key_pressed(clone!(@weak controller => @default return gtk::Inhibit(false); move |_ctlr, key, _code, state| {
    controller.keyboard_input(key, state);
    gtk::Inhibit(false)
}));

这样修改后,宏生成的代码在弱引用升级失败时会返回gtk::Inhibit(false),和闭包要求的返回类型匹配,编译就能通过了。


备注:内容来源于stack exchange,提问作者russell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 11:22:45