How can I run a command line from a GTK app (C++) and redirect silmutaneously the output stream in a GTK object?
<p>I'm building a <strong>graphical interface using C++ and GTK 3.0</strong>.<br>
From this, I would like to <strong>run another C++ program</strong> (let's call it BOB) and <strong>get the STDOUT and STDERR informations <em>simultaneously</em> on my interface</strong>.</p>

<p>The command line to run BOB from a console is :
<em>./BOB_executable_file parameter_file</em><br>
I manage to run it from the interface, with <strong>popen()</strong> or <strong>g_spawn_command_line_sync()</strong> and the outputs are printed directly into the console (I launched the interface from the console).</p>

<p>The best I managed to have is to have the command line running but which need to be completely finished so the outputs can be printed : <strong>it's not direct and simultaneous redirection</strong>...</p>

<ul>
<li><p>redirect the STDOUT and STDERR into files with <strong>popen()</strong>:</p>

<pre><code>  //command line storing STDOUT and STDERR into files
  const gchar* command = ("./BOB_executable_file param_file &gt; FATE_stdout.txt 2&gt;FATE_stderr.txt").c_str();
  //running the command
  FILE* pipe = popen(command,"r");

  string temp, line;
  gchar* res;
  GtkWidget* pLabel;

  //opening the STDOUT file
  ifstream file("FATE_stdout.txt", ios::in);
  while (getline(file,line)){ //for each line read from the file
      temp = line;
      res = g_locale_to_utf8(temp.c_str(),-1,NULL,NULL,NULL); //convert it to utf8
      pLabel = gtk_label_new(NULL); //create an empty label
      gtk_label_set_markup(GTK_LABEL(pLabel),res); //update the label with the line
      gtk_box_pack_start(GTK_BOX(myBox), pLabel, TRUE, TRUE, 0); //add the label to myBox which is a vertical box
      gtk_widget_show_all((GtkWidget*) data); //show the new line
  }
</code></pre></li>
<li><p>redirect the STDOUT and STDERR into objects with <strong>g_spawn_command_line_sync</strong>:</p>

<pre><code>  gchar *output_txt, *error_txt;       
  GError *error = NULL;

  //command line storing STDOUT and STDERR into files
  const gchar* command = ("./BOB_executable_file param_file &gt; FATE_stdout.txt 2&gt;FATE_stderr.txt").c_str();
  //running the command
  g_spawn_command_line_sync(command, &amp;output_txt, &amp;error_txt, NULL, &amp;error);

  if (error != NULL){
      errorMessage(error-&gt;message);  
      g_error_free(error);
      return;
  }

  //add the label to myBox1 and myBox2 which are vertical boxes
  gtk_box_pack_start(GTK_BOX(myBox1), gtk_label_new(output_txt), TRUE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(myBox2), gtk_label_new(error_txt), TRUE, TRUE, 0);
  gtk_widget_show_all((GtkWidget*) data);
</code></pre></li>
</ul>

<p><strong>BUT</strong> in both cases, the command line has to be completely finished so the outputs can be printed : <strong>it's not direct and simultaneous redirection</strong>...</p>

<p>I also tried to use <strong>GIO stuff</strong> (I tried with STDOUT and STDERR files created either with <strong>g_spawn_command_line_sync()</strong> or <strong>g_spawn_async_with_pipes()</strong> or <strong>popen</strong>) but it's still not simultaneous and the interface crashes :</p>

<pre><code>      GIOChannel* outchannel = g_io_channel_new_file("FATE_stdout.txt","r",NULL);
      g_io_add_watch (outchannel, (GIOCondition)(G_IO_IN), on_pipe_output, (gpointer) view_output);

      GIOChannel* errchannel = g_io_channel_new_file("FATE_stderr.txt","r",NULL);
      g_io_add_watch (errchannel, (GIOCondition)(G_IO_ERR), on_pipe_output, (gpointer) view_error);
</code></pre>

<p>with <em>view_output</em> and <em>view_error</em> some TextView with buffers inside and the listening function <em>on_pipe_output</em> :</p>

<pre><code>      void scroll_to_end(GtkWidget* textview){
        GtkTextBuffer *buffer;
        GtkTextIter enditer;

        buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(textview));
        gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER (buffer), &amp;enditer);
        gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview), &amp;enditer, 0, TRUE, 0.0, 0.0);
      }

      void addMsgInfo(GtkWidget* textview, gchar *buf){
        GtkTextBuffer *buffer;
        GtkTextIter  enditer;

        buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
        gtk_text_buffer_get_end_iter (GTK_TEXT_BUFFER (buffer), &amp;enditer);
        gtk_text_buffer_insert(buffer, &amp;enditer,buf,-1);
        g_idle_add ((GSourceFunc)scroll_to_end, NULL);
      }

      gboolean on_pipe_output (GIOChannel *source, GIOCondition condition, gpointer data){
        gchar buffer[BUFSIZ+1];
        gsize *bytes_read;
        g_io_channel_read_chars(source,buffer,BUFSIZ,bytes_read,NULL);

        addMsgInfo((GtkWidget*) data, buffer);
      }
</code></pre>

<p>Does anyone have already deal with such problem and has a solution or improvement ?</p>