Strumenti Utente

Strumenti Sito


programmazione:gtk:catturare_output_di_una_pipe

Differenze

Queste sono le differenze tra la revisione selezionata e la versione attuale della pagina.

Link a questa pagina di confronto

Prossima revisione
Revisione precedente
programmazione:gtk:catturare_output_di_una_pipe [18/04/2018 - 15:48]
127.0.0.1 modifica esterna
programmazione:gtk:catturare_output_di_una_pipe [05/05/2023 - 11:10]
Fabio Di Matteo
Linea 1: Linea 1:
 ====== Catturare l'​output di una pipe e stamparlo dentro una textview ====== ====== Catturare l'​output di una pipe e stamparlo dentro una textview ======
-Autore: **//Fabio Di Matteo//** \\ Ultima revisione: **//24/02/2018  ​- ​19:24//** \\ \\+Autore: **//Fabio Di Matteo//** \\ Ultima revisione: ​ **//  05/05/2023  ​- ​11:09   //**  // //
  
 +{{:​programmazione:​gtk:​glib_get_output.png?​500|}}
 +
 +===== Versione GLib =====
 +
 +**main.c**
 +<code c>
 +#include <​gtk/​gtk.h>​
 +
 +GObject *myEntry, *myButton, *myTextView,​ *myProgressBar,​ *myScrolledWindow;​
 +GtkTextBuffer *buffer;
 +GtkBuilder *xml;
 +
 +void on_mainWindow_delete_event(GtkWidget *widget, gpointer ​  data)
 +{
 + g_print("​Ciao ciao...\n"​);​
 + gtk_main_quit();​
 +}
 +
 +
 +void scrollToEnd(GtkWidget *widget, gpointer ​  data)
 +{
 + GtkAdjustment * adj=gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(myScrolledWindow));​
 + gdouble upper=gtk_adjustment_get_upper(GTK_ADJUSTMENT(adj));​
 + gtk_adjustment_set_value (GTK_ADJUSTMENT(adj), ​ upper);
 +}
 +
 +//Semplice funzione che aggiorna la textview
 +gboolean appendTextView(gchar* out)
 +{
 + gtk_text_buffer_insert_at_cursor (buffer,​out,​ -1);
 + gtk_text_view_set_buffer (GTK_TEXT_VIEW(myTextView),​buffer);​
 +
 + return FALSE;
 +}
 +
 +
 +//Callback che viene chiamata ogni qualvolta c'è dello standard output da mostrare
 +static gboolean
 +cb_out_watch( GIOChannel ​  ​*channel,​ GIOCondition ​ cond, gpointer user_data )
 +{
 +    gchar *string;
 +    gsize  size;
 +
 + if( cond == G_IO_HUP )
 + {
 + g_io_channel_unref( channel );
 + return( FALSE );
 + }
 +
 + //Leggo la riga corrente dallo stdout e la salvo in "​string"​
 + g_io_channel_read_line( channel, &​string,​ &size, NULL, NULL );
 +
 + //Formatto e stampo a video "​string"​ e dopo libero string dalla memoria
 + gchar* s=g_strdup_printf("​%s",​string);​
 + //​g_idle_add ((GSourceFunc) appendTextView,​ s ); //mostro nel textview
 + g_idle_add_full (G_PRIORITY_HIGH_IDLE,​ (GSourceFunc) appendTextView,​ s, NULL); //mostro nel textview ad alta priorita'​
 + printf("​%s",​ s);
 + g_free( string );
 +
 + return( TRUE );
 +}
 +
 +//Callback che viene chiamata ogni qualvolta c'è dello standard error da mostrare
 +static gboolean
 +cb_err_watch( GIOChannel ​  ​*channel,​ GIOCondition ​ cond, gpointer user_data )
 +{
 +    gchar *string;
 +    gsize  size;
 +
 + if( cond == G_IO_HUP )
 + {
 + g_io_channel_unref( channel );
 + return( FALSE );
 + }
 +
 + g_io_channel_read_line( channel, &​string,​ &size, NULL, NULL );
 +
 + //Formatto e stampo a video "​string"​ e dopo libero string dalla memoria
 + gchar* s=g_strdup_printf("​Errore:​ %s",​string);​
 + g_idle_add ((GSourceFunc) appendTextView,​ s ); //mostro nel textview
 + printf("​%s",​ s);
 + g_free( string );
 +
 + return( TRUE );
 +}
 +
 +
 +void *runCommandPipe(gchar* cmd)
 +{
 + GPid        pid; //il processid del processo figlio
 + gchar  ​  ​*workingDir ="/​usr/​bin/"​ ;​ //la directory corrente dove si trova l'​eseguibile
 + gchar **launch = g_strsplit (cmd," ",0); //crea un array di stringhe a partire da una stringa di char
 + gint        in, //file descriptor per l'​input (non usato) ​
 + out, //file descriptor per l'​stdoutput
 + err; //file descriptor per lo stderr
 + GIOChannel *out_ch, //canale per catturare l'​output
 +    ​*err_ch;​ //canale per catturare gli errori
 + gboolean ​   ret; // se g_spawn_async_with_pipes ha successo è TRUE
 + GError **error; //array per catturare gli eventuali errori all'​avvio di g_spawn_async_with_pipes
 +
 + /* Avvia il processo figlio in background */
 + ret = g_spawn_async_with_pipes( workingDir, launch, NULL,
 + G_SPAWN_DEFAULT,​ NULL,
 + NULL,​ &pid, &in, &out, &err, error );
 + if( ! ret )
 + {
 + g_error( "Pipe fallita."​ );
 + }
 +
 + //Creiamo i canali che servono per leggere i dati dalla pipe. 
 + out_ch = g_io_channel_unix_new( out );
 + err_ch = g_io_channel_unix_new( err );
 +
 + // Creiamo i watch per ogni canale creato ​
 + // in pratica ogni volta che la pipe restituisce dell'​output dallo stdout
 + // oppure dallo stderr vengono esseguite le relative funzioni callbacks
 + g_io_add_watch( out_ch, G_IO_IN | G_IO_HUP, (GIOFunc)cb_out_watch,​ NULL );
 + g_io_add_watch( err_ch, G_IO_IN | G_IO_HUP, (GIOFunc)cb_err_watch,​ NULL );
 +
 +
 + if (error != NULL)
 + {
 +   printf("​Errore nella pipe\n"​);​
 + }
 +
 +}
 +
 +
 +
 +
 +void myButton_clicked_cb(GtkWidget *widget, gpointer ​  data)
 +{
 + //Pulisco tutto il textBuffer
 + gtk_text_buffer_set_text (GTK_TEXT_BUFFER(buffer),"",​0);​
 +
 + gchar* cmd= g_strdup_printf("​%s",​ gtk_entry_get_text(GTK_ENTRY(data)));​
 + g_print("​Comando->​ %s\n",​cmd);​
 +
 + //Un thread avvia la funzione che eseguira'​ la pipe
 + GThread ​  ​*myThread; ​
 + myThread= g_thread_new(NULL,​(GThreadFunc)runCommandPipe,​cmd);​
 +}
 +
 +void mainWindowInit()
 +{
 + GError* error = NULL;
 + gchar* glade_file = g_build_filename("​gui.ui",​ NULL);
 +   ​
 + GObject *mainWindow ;
 + buffer=gtk_text_buffer_new (NULL);
 +
 + xml = gtk_builder_new ();
 + if (!gtk_builder_add_from_file ​ (xml, glade_file, &​error))
 + {
 + g_warning ("​Couldn\'​t load builder file: %s", error->​message);​
 + g_error_free (error);
 + }
 +
 + mainWindow=gtk_builder_get_object (xml,"​mainWindow"​ );
 + myScrolledWindow=gtk_builder_get_object (xml,"​myScrolledWindow"​ );
 + g_signal_connect (myScrolledWindow,​ "​size-allocate",​ G_CALLBACK (scrollToEnd),​ NULL);
 + myButton=gtk_builder_get_object (xml,"​myButton"​ );
 + myEntry=gtk_builder_get_object(xml,"​myEntry"​);​
 + myTextView=gtk_builder_get_object(xml,"​myTextView"​);​
 + myProgressBar=gtk_builder_get_object(xml,​ "​myProgressBar"​);​
 + gtk_entry_set_text(GTK_ENTRY(myEntry),"​rsync -avz --info=progress2 --dry-run /usr/bin/ /​home/​fabio/​Desktop/​tt/"​);​
 +
 + g_signal_connect(myButton,"​clicked",​G_CALLBACK(myButton_clicked_cb),​myEntry);​
 + g_signal_connect(mainWindow,"​delete-event",​G_CALLBACK(on_mainWindow_delete_event),​NULL);​
 + g_object_unref( G_OBJECT( xml ) );
 +
 +
 +}
 +
 +
 +
 +
 +int main (int    argc,  char **argv)
 +{
 +
 + gtk_init (&argc, &argv);
 + mainWindowInit();​
 + gtk_main ();
 +
 +  return 0;
 +}
 +
 +</​code>​
 +
 +**makefile**
 +<​file>​
 +all:
 + gcc  main.c -o simple ​ `pkg-config --cflags --libs gtk+-3.0 gthread-2.0 ​ gmodule-2.0`
 +
 +
 +</​file>​
 +
 +**gui.glade**
 +<code xml>
 +<?xml version="​1.0"​ encoding="​UTF-8"?>​
 +<!-- Generated with glade 3.22.1 -->
 +<​interface>​
 +  <​requires lib="​gtk+"​ version="​3.20"/>​
 +  <object class="​GtkWindow"​ id="​mainWindow">​
 +    <​property name="​width_request">​500</​property>​
 +    <​property name="​height_request">​300</​property>​
 +    <​property name="​visible">​True</​property>​
 +    <​property name="​can_focus">​False</​property>​
 +    <signal name="​delete-event"​ handler="​on_mainWindow_delete_event"​ swapped="​no"/>​
 +    <child type="​titlebar">​
 +      <​placeholder/>​
 +    </​child>​
 +    <​child>​
 +      <object class="​GtkBox">​
 +        <​property name="​visible">​True</​property>​
 +        <​property name="​can_focus">​False</​property>​
 +        <​property name="​orientation">​vertical</​property>​
 +        <​child>​
 +          <object class="​GtkBox">​
 +            <​property name="​visible">​True</​property>​
 +            <​property name="​can_focus">​False</​property>​
 +            <​child>​
 +              <object class="​GtkEntry"​ id="​myEntry">​
 +                <​property name="​width_request">​508</​property>​
 +                <​property name="​visible">​True</​property>​
 +                <​property name="​can_focus">​True</​property>​
 +              </​object>​
 +              <​packing>​
 +                <​property name="​expand">​False</​property>​
 +                <​property name="​fill">​True</​property>​
 +                <​property name="​position">​0</​property>​
 +              </​packing>​
 +            </​child>​
 +            <​child>​
 +              <object class="​GtkButton"​ id="​myButton">​
 +                <​property name="​label">​gtk-execute</​property>​
 +                <​property name="​visible">​True</​property>​
 +                <​property name="​can_focus">​True</​property>​
 +                <​property name="​receives_default">​True</​property>​
 +                <​property name="​use_stock">​True</​property>​
 +                <​property name="​always_show_image">​True</​property>​
 +                <signal name="​clicked"​ handler="​myButton_clicked_cb"​ object="​myEntry"​ swapped="​no"/>​
 +              </​object>​
 +              <​packing>​
 +                <​property name="​expand">​False</​property>​
 +                <​property name="​fill">​True</​property>​
 +                <​property name="​position">​1</​property>​
 +              </​packing>​
 +            </​child>​
 +          </​object>​
 +          <​packing>​
 +            <​property name="​expand">​False</​property>​
 +            <​property name="​fill">​True</​property>​
 +            <​property name="​position">​0</​property>​
 +          </​packing>​
 +        </​child>​
 +        <​child>​
 +          <object class="​GtkScrolledWindow"​ id="​myScrolledWindow">​
 +            <​property name="​height_request">​400</​property>​
 +            <​property name="​visible">​True</​property>​
 +            <​property name="​can_focus">​True</​property>​
 +            <​property name="​shadow_type">​in</​property>​
 +            <​child>​
 +              <object class="​GtkTextView"​ id="​myTextView">​
 +                <​property name="​visible">​True</​property>​
 +                <​property name="​can_focus">​True</​property>​
 +              </​object>​
 +            </​child>​
 +          </​object>​
 +          <​packing>​
 +            <​property name="​expand">​False</​property>​
 +            <​property name="​fill">​True</​property>​
 +            <​property name="​position">​1</​property>​
 +          </​packing>​
 +        </​child>​
 +        <​child>​
 +          <object class="​GtkProgressBar"​ id="​myProgressBar">​
 +            <​property name="​height_request">​15</​property>​
 +            <​property name="​visible">​True</​property>​
 +            <​property name="​can_focus">​False</​property>​
 +            <​property name="​text"​ translatable="​yes">​Pronto.</​property>​
 +            <​property name="​show_text">​True</​property>​
 +          </​object>​
 +          <​packing>​
 +            <​property name="​expand">​False</​property>​
 +            <​property name="​fill">​True</​property>​
 +            <​property name="​position">​2</​property>​
 +          </​packing>​
 +        </​child>​
 +      </​object>​
 +    </​child>​
 +  </​object>​
 +</​interface>​
 +
 +</​code>​
 +
 +
 +===== Versione Posix =====
  
 <code c> <code c>

programmazione/gtk/catturare_output_di_una_pipe.txt · Ultima modifica: 05/05/2023 - 11:10 da Fabio Di Matteo