Hi, I'm looking for a way to redirect stdout to a Gtk::TextView
widget in gtkmm. Ideally, I want it to work both on Windows and UNIX-like OSes.
So far, I've tried to redirect stdout to a file, then monitor changes to this file using Glib, like so (highly inspired from the gtkmm examples on gnome.org) :
#include <stdio.h>
#include <fcntl.h>
#include <gtkmm-2.4/gtkmm.h>
// In main
freopen("stdout.log", "w", stdout);
MyClass mc;
Gtk::Main::run(mc);
fclose(stdout);
// Global variables :
int fd;
Gtk::TextView tv;
Glib::RefPtr<Gtk::TextBuffer> txtBuffer;
Glib::RefPtr<Glib::IOChannel> iochannel;
// In constructor of MyClass :
fd = open("stdout.log", O_RDONLY);
Glib::signal_io().connect(sigc::mem_fun(*this,&MyClass::on_stdout_change), fd, Glib::IO_IN);
iochannel = Glib::IOChannel::create_from_fd(fd);
txtBuffer = tv.get_buffer();
// Callback method on_stdout_change :
bool MyClass::on_stdout_change(Glib::IOCondition io_condition) {
if ((io_condition & Glib::IO_IN) == 0) {
std::cerr << "Invalid file response" << std::endl;
}
else {
Glib::ustring buf;
#ifdef GLIBMM_EXCEPTIONS_ENABLED
iochannel->read_line(buf);
#else
std::auto_ptr<Glib::Error> ex;
iochannel->read_line(buf, ex);
if(ex.get())
std::cerr << "Error: " << ex->what() << std::endl;
#endif //GLIBMM_EXCEPTIONS_ENABLED
Gtk::TextIter iter = txtBuffer->end();
txtBuffer->insert(iter, buf);
}
return true;
}
Now, this compiles and runs, but it hangs right after the application window appears. The window remains gray and empty. If I try to send buf
to std::cerr
, I can see in the terminal window that many blank lines are being written. If that is so, it must mean there is constant calling of the callback function, as if data was ready to be read from stdout.log
constantly. I would expect there would only be something to be read when I actually send stuff to stdout
.
Any suggestions on how to do this or explanations about what is happening are greatly appreciated.