LINUX.ORG.RU

Вопрос связанный с GTK+/Си.


0

0

Пытаюсь решить одну проблему, возможно кто-нибудь поможет.

/* создаем диалоговое окно */
GtkWidget *dialog = gtk_dialog_new_with_buttons ("hello", main_window, GTK_DIALOG_MODAL, NULL);
/* запаковываем в него виджет */
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), gtk_label_new("данное окно закроется как только будет закрыт gvim"), TRUE, TRUE, 0);
/* добавляем еще виджетов, кнопок и т.д. */
/* ... */
/* показываем все виджеты */
gtk_widget_show_all (dialog);
/* запускаем gvim */
int e;
g_spawn_command_line_sync ("gvim", NULL, NULL, &e, NULL)
/* запускаем диалог */
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);

Мне нужно, чтобы диалоговое окно закрылось сразу же после закрытия gvim'а.
Т.е мне нужно как-то (как?) постоянно следить за gvim'ом и как только он завершит работу,
закрыть диалоговое окно (т.е. как-то отследить, что gvim закрылся).

Как этого добиться?
anonymous

открывать диалоговое окно как дочерний процесс gvim'a? Только нужно будет в сорсах gvim'a покопаться.

anonymous
()

> (т.е. как-то отследить, что gvim закрылся).

g_spawn_sync with pipes или чёто такое - не помню, запустив так, узнаешь пид гвима, а зная его легко контролировать процесс гвима.

Pi ★★★★★
()
Ответ на: комментарий от lg

>открывать диалоговое окно как дочерний процесс gvim'a? Только нужно будет в сорсах gvim'a покопаться.


Нет. Из своей программы хочу запускать внешние программы (что-то будет вроде фронтенда).
Gvim приведен для примера, на самом деле будут запускаться консольные утилиты.
Т.е. запускаю диалог, и пока консольная программа в фоне что-то делает диалог показывает progressbar.
Как только консольные утилиты отработают, диалоговое окно закрывается.


>узнаешь пид гвима, а зная его легко контролировать процесс гвима.


вот-вот! Как раз про это я и спрашиваю.
Перефразирую вопрос: как зная пид процесса (будь то pid_t или глибовский GPid), определить:
данный процесс существует или нет?

anonymous
()
Ответ на: комментарий от anonymous

поставить себе glib >= 2.4 и использовать функцию

guint       g_child_watch_add               (GPid pid,
                                             GChildWatchFunc function,
                                             gpointer data);

Sets a function to be called when the child indicated by pid exits, at a default priority, G_PRIORITY_DEFAULT.

Note that on platforms where GPid must be explicitely closed (see g_spawn_close_pid()) pid must not be closed while the source is still active. Typically, you will want to call g_spawn_close_pid() in the callback function for the source.

pid :	process id of a child process to watch
function :	function to call
data :	data to pass to function
Returns :	the id of event source.

anonymous
()
Ответ на: комментарий от anonymous

/*
спасибо, похоже это то, что я ищу.
но вот то ли я плохо разобрался в функциях, то ли еще чего - вобщем не работает :(

ниже код, может кто отыщет ошибку
*/

void x_func (GPid pid, gint status, gpointer data)
{	
	puts ("Данная функция должна вызваться после того, как gvim завершит работу.\nНо он не вызывается!");
	gtk_widget_destroy (data); /* закрываем диалог */
}

/* запускаем диалоговое окно */
void test_func () 
{
	GtkWidget *dialog, *cancel_button;

	dialog = gtk_dialog_new_with_buttons ("test", GTK_WINDOW (main_window), GTK_DIALOG_MODAL, NULL);

	cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
	gtk_dialog_add_action_widget (GTK_DIALOG(dialog), cancel_button, GTK_RESPONSE_CANCEL);

	gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox), gtk_label_new ("Данный диалог должен закрыться после завершения работы gvim"), 0, 0, 0);

	gtk_widget_show_all (dialog);
	
	/* -------------------------------- */
	/* запускаем  gvim */
	char *argv[] = { "gvim", NULL};
	GError *error;
	GPid child_pid;
	
	g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, &child_pid, &error);

	/* здесь выводим пид запущенного gvim'а, что интересно выводится число 
	   на единицу меньше, чем то, что выводит 'ps -A | grep gvim' */
	printf ("Созданный процесс имеет пид номер %d\n", child_pid);

	/* не работает! */
	g_child_watch_add (child_pid, x_func, dialog);
	/* не работает даже так:
	   g_child_watch_add (++child_pid, x_func, dialog);
	*/

	/* -------------------------------- */

	gtk_dialog_run (GTK_DIALOG (dialog));
	gtk_widget_destroy (dialog);
}

anonymous
()
Ответ на: комментарий от anonymous

не мучайся ты с энтим адд_вач

посылай по таймеру ему kill(0)

man 2 kill

Pi ★★★★★
()
Ответ на: комментарий от anonymous

Извините, моя ошибка. Видимо g_spawn слишком навороченные функции и для такой задачи не подходят. Нужно будет этот вопрос изучить. А пока могу сказать, что такая реализация при помощи fork+exec у меня работает.


#include <unistd.h>
#include <gtk/gtk.h>
#include <glib.h>

void x_func (GPid pid, gint status, gpointer data)
{	
	g_message ("Hello again");
	gtk_widget_destroy (data); 
}

void y_func (GObject *dialog, gpointer data)
{	
	g_message ("Hello again and again");
	gtk_widget_destroy (GTK_WIDGET(dialog)); 
}

void test_func (GObject *obj, gpointer data) 
{
	GtkWidget *dialog, *cancel_button;
	GPid child_pid;

	dialog = gtk_dialog_new_with_buttons ("test", NULL, GTK_DIALOG_MODAL, NULL);

	cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
	gtk_dialog_add_action_widget (GTK_DIALOG(dialog), cancel_button, GTK_RESPONSE_CANCEL);

	gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox), gtk_label_new("Gvim started"), 0, 0, 0);

	gtk_widget_show_all (dialog);
	
	if ((child_pid = fork ()) == 0) {
	    execlp ("xcalc", "", NULL);
	}

	g_child_watch_add (child_pid, x_func, dialog);

	g_signal_connect (dialog,
    	                 "response", 
        	          G_CALLBACK (y_func),
                	  dialog);
	return;
}


int main( int   argc,
          char *argv[] )
{
    GtkWidget *window;
    GtkWidget *button;

    g_thread_init (NULL);
    gtk_init (&argc, &argv);
    
    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    
    button = gtk_button_new_with_label ("Hello World");

    g_signal_connect (G_OBJECT (button), "clicked",
		      G_CALLBACK (test_func), NULL);
    
    gtk_container_add (GTK_CONTAINER (window), button);
    gtk_widget_show_all (window);
    
    gtk_main ();
    
    return 0;
}

anonymous
()
Ответ на: комментарий от anonymous

А, ну да, нужно добавлять еще флаг G_SPAWN_DO_NOT_REAP_CHILD, тогда и первый пример будет работать номально.

g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &child_pid, &error);

anonymous
()
Ответ на: комментарий от anonymous

Спасибо.

> А, ну да, нужно добавлять еще флаг G_SPAWN_DO_NOT_REAP_CHILD, тогда и первый пример будет работать номально.

Вроде не совсем нормально, но это не важно, буду форк-екзек юзать.
Еще раз спасибо.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.