如何从 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;
}
这就是你的做法。
我正在编写一个 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;
}
这就是你的做法。