如何从 GTK+ 程序中调用程序,并分析程序的输出?

How do I call a program from a GTK+ program, and analyze the program's output?

我正在编写一个 GTK+ 前端程序来粉碎文件。来自 GNU Coreutils 的程序 shred 是后端。编程语言为C.

所以,我有一个进度条显示完成了多少碎化。但是,为了向用户提供有关粉碎量的准确数据,必须分析粉碎的输出。

到目前为止,我已尝试 g_spawn_command_line_async,但我无法将 shred 的输出发送到文件。

最简单的解决方案是使用 unix 重定向。您可以调用 system("shred -v file_to_shred > somefile.txt"),输出将重定向到文件。然后,您可以使用 POSIX read 或其他一些文件读取方法从文件中读取。 运行 system() 在单独的线程中调用,然后在主线程中增量检查文件。您可以使用 POSIX sleep() 每隔一段时间检查一次文件,比如每半秒检查一次。但是,切勿在 GUI 线程上使用睡眠,因为这会冻结 UI.

这可以通过 GSubprocess(来自 GIO)实现。这是简化的源代码。 为此,您需要安装 gimp。 (它显示来自选项 --help 的帮助文本)

#include <gtk/gtk.h>

struct everything
{
    GtkWidget *window;
    GtkWidget *box;
    GtkWidget *new_process;
    GtkWidget *gimp_help_label;
};

void on_new_process_clicked (GtkWidget *wid, gpointer data)
{
    struct everything *wids = data;

    GError *error = NULL; /* This contains and error that MAY be generated by the gio functions. */
    GInputStream *stdout_output;
    GSubprocess *process;
    gchar hello[10000];

    process = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, "gimp", "--help", NULL);
    stdout_output = g_subprocess_get_stdout_pipe(process);

    g_input_stream_read (stdout_output, hello, 9995, NULL, &error);

    gtk_widget_hide(wids->new_process); /* Hide the button */
    wids->gimp_help_label = gtk_label_new(hello); /* Make a new label. */
    gtk_box_pack_start(GTK_BOX(wids->box), wids->gimp_help_label, TRUE, TRUE, 20); /* Add it to the box. */
    gtk_widget_show(wids->gimp_help_label); /* Show it */
}

void exit_prog (GtkWidget *wid, gpointer data)
{
    gtk_main_quit();
}

int main(int argc, char **argv)
{
    gtk_init(&argc, &argv);

    struct everything *widgets = (struct everything*)malloc(sizeof(struct everything));

    widgets->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(widgets->window), 500, 500);
    g_signal_connect(widgets->window, "destroy", G_CALLBACK(exit_prog), NULL);

    widgets->box = gtk_vbox_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(widgets->window), widgets->box);

    widgets->new_process = gtk_button_new_with_label("Show Gimp Help");
    gtk_box_pack_start(GTK_BOX(widgets->box), widgets->new_process, TRUE, TRUE, 20);
    g_signal_connect(widgets->new_process, "clicked", G_CALLBACK(on_new_process_clicked), widgets);

    gtk_widget_show_all(widgets->window);

    gtk_main();
    return 0;
}

这就是你的做法。