如何在 `connect_activate()` 之外创建一个 `glib::MainContext::channel()` 然后将其传入?

问题描述 投票:0回答:1

我是 Rust 和 GTK 的新手。我想在初始化我的

glib::MainContext::channel()
之前创建一对
gtk::Application
。我相信这可以完全理解为
std::sync::mpsc
。虽然我可以创建 rx/tx 通道对并保存它,但我不确定如何将
Receiver
传递到
gtk::Application::connect_activate()
信号处理程序中,以便我可以
.attach()
它。

例如,我修改了这个样本

struct MyData {
    ready_tx: glib::Sender<i32>,
    //ready_rx: glib::Receiver<i32>,
}

fn setup() -> MyData {
    let (ready_tx, ready_rx) = glib::MainContext::channel(glib::Priority::default());
    MyData {
        ready_tx,
        //ready_rx,
    }
}

fn main() {
    let data = setup();

    //
    // Setup other threads by cloning data.sender
    //

    let application = gtk::Application::new(
        Some("com.github.gtk-rs.examples.cairo_threads"),
        Default::default(),
    );

    application.connect_activate(move |app| {
        build_ui(&app, &data)
    });

    application.run();
}

fn build_ui(application: &gtk::Application, data: &MyData) {
    ...
    data.ready_rx.attach( {
        ...
    });
}

上面的代码可以编译并运行(忽略已删除的

build_ui
),但有一个明显的问题:
ready_tx
实际上并未包含在内。

这样做会导致“发生移动,因为

data.ready_rx
具有类型
glib::Receiver<i32>
,它没有实现
Copy
内的
build_ui()
特征”。

我希望

Receiver<i32>
的所有权从
setup()
函数转移到
main
,并最终被
build_ui()
函数消耗,但我不确定如何到达那里或我做什么我失踪了。我不确定为什么需要
Copy
,但我知道我不能
.clone()
Receiver

有什么想法吗?

我想这样做,因为我需要先设置一些额外的线程,在初始化 GTK GUI 之前,这些线程需要引用

Sender
。我还没有找到任何在
glib::MainContext::channel()
函数之外创建
build_ui()
对的好例子。

我应该考虑其他方法吗?

rust gtk borrow-checker gtk-rs
1个回答
0
投票

如果您只需要

Receiver
一次,请将
Option<Receiver>
take().unwrap()
存储在
build_ui()
中,为此您将需要对
MyData
的可变引用。

如果您无法提供可变引用(我相信GTK就是这种情况),您可以存储一个

Cell<Option<Receiver>>
,然后
take().unwrap()
它。这只需要共享引用,因为
Cell
具有内部可变性。

© www.soinside.com 2019 - 2024. All rights reserved.