每当 gtk 应用程序 运行 多次时,g_application_parse_command_line 中的断言失败

Assertion fails in g_application_parse_command_line whenever gtk application run multiple times

如果我想多次 运行 一个 gtk 应用程序,我的 Gtk-rs 程序会崩溃。

use gio::prelude::*;
use gtk::prelude::*;

static APP_ID: &'static str = "com.localserver.app";

fn build_ui(app: &gtk::Application, fallback_message: Option<&'static str>) {
    {
        let window = gtk::ApplicationWindow::new(app);
        window.set_title("App");
        window.set_position(gtk::WindowPosition::Center);
        window.set_default_size(350, 70);

        window.add(&gtk::Label::new(Some(
            fallback_message.unwrap_or("Hello world"),
        )));

        window
    }
    .show_all();
}

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    let application: gtk::Application =
        gtk::Application::new(Some(APP_ID), Default::default()).unwrap();
    application.connect_activate(|app| build_ui(&app, None));

    for n in 1 .. 4 {
        application.run(&args);
        println!("Window loaded {} times.", n);
    }
}

当运行时,它在最后的for循环中进行了第一次迭代,但在下一次崩溃了:

(dbustest_rs:9805): GLib-GIO-CRITICAL **: 19:23:51.883: g_application_parse_command_line: assertion '!application->priv->options_parsed' failed
Segmentation fault (core dumped)

是什么原因造成的,我该如何预防?

问题是对 GTK 中发生的事情和对象层次结构的简单误解。

GTK 的对象树以 Application 开头,您的情况就是这样。然后它有 1 个或多个 ApplicationWindows,它们是 "windows" 本身。从那里开始,您的所有组件都在那个之下。

您已正确完成此层次结构 - 您在 Application 下创建了您的 ApplicationWindow。但是,您随后决定 run() 该应用程序四次,并且在库内部进行检查以查看参数之前是否已被解析。因为它是相同的(回收的)应用程序,所以它们是错误的。

考虑每次都重新创建 Application;它也遵循自然的 GTK 生命周期。