Hi, Sorry to flood the list with my broken pipes stories but I finally found a way to get this to work! hurray! Here is a solution.
The following code just spawn a shell to which you can send commands. #include <glibmm.h> #include <gtkmm/main.h> #include <vector> #include <string> #include <iostream> Glib::RefPtr<Glib::IOChannel> ch_stdout; bool callback(Glib::IOCondition cond) { Glib::ustring buf; ch_stdout->read_line(buf); //ch_stdout->read_to_end(buf) would never //return for an unknown reason std::cout<<buf; return true; } int main(int argc, char** argv) { Gtk::Main kit(argc,argv); int fd_stdout, fd_stdin; Glib::Pid pid; std::vector<std::string> arguments; arguments.push_back("sh"); Glib::spawn_async_with_pipes(Glib::get_current_dir(),arguments, Glib::SPAWN_SEARCH_PATH | Glib::SPAWN_CHILD_INHERITS_STDIN, sigc::slot<void>(), &pid,/*&fd_stdin*/0,&fd_stdout); ch_stdout=Glib::IOChannel::create_from_fd(fd_stdout); Glib::signal_io().connect(sigc::ptr_fun(callback), ch_stdout,Glib::IO_IN); kit.run(); return 0; } To summerize what I did to get it to work: - The output Glib::IOChannel must be flushed for the data to be actually written in the pipe (not shown in the example). I know this looks trivial but it took me a while to figure it out since it's never mentionned in the reference documentation. - for the watch function, connect the input Glib::IOChannel directly using: Glib::signal_io().connect(const sigc::slot<bool,IOCondition>, const IOChannel&, IOCondition, int); rather than using the version taking the file descriptor instead of the IOChannel. - Read a line at a time in the callback function. If there is more to be read, the callback function will be called again anyway. I think this is quite weird that Glib::IOChannel::read_to_end can be in a condition where it never returns and would call it a bug! Note that this is not a c++ binding issue since trying to do the same in C did produce the same result. I hope this might be of use to someone! Cheers! Le dimanche 18 octobre 2009 à 19:32 +0200, Bastien Dalla Piazza a écrit : > Hi again, I partially solved my problem: > > One needs to call Glib::IOChannel::flush() after writing on outgoing > pipe for the message to be passed. > For the ingoing pipe, it is necessary to add a watch function using for > instance > > Glib::io_signal().connect(sigc::mem_fun(&object,Object::callback),ingoing_fd, > Glib::IO_IN); > > I'm running into an other problem: Using the abow call, the function > > bool Object::callback(Glib::IOCondition cond) > > will be called each time the Glib::IO_IN condition is set on the ingoing > pipe, that is when there is something to read. > > But trying to read in the above callback function using > > Glib::IOChannel::read_to_end > > results in an infinite loop (at least it looks like it). > The Glib::IOChannel::read_line still works so I tried the following > workaround: > > Glib::ustring store,buf; > while(ingoing->get_condition() & Glib::IO_IN){ > ingoing->readline(buf); > store.append(buf); > } > > The while loop seems to finish, but then my callback function keeps > being called over and over again by the main loop (Gtk::Main::run()), as > if the Glib::IO_IN condition was never unset although the above while > loop did finish. > > Am I doing things in an unexpected way, or is it possible there is a bug > in Glib::IOChannel ? > > Thanks! > > Le samedi 17 octobre 2009 à 17:37 +0200, Bastien Dalla Piazza a écrit : > > Hi, > > > > I don't know if this is the correct mailing list so redirect me if not. > > > > In a Gtkmm project, I'm using Glib::spawn_async_with_pipes to execute > > and control a child process (gnugo in the example). But I cannot get it > > to work! > > For example: > > In the following code, I just redirect the gnugo stdin and stdout to my > > program: > > > > #include <glibmm.h> > > #include <vector> > > #include <string> > > #include <iostream> > > > > int main(int argc, char** argv) > > { > > Glib::init(); > > > > int fd_stdin, fd_stdout; //file descriptors > > Glib::Pid pid; > > Glib::RefPtr<Glib::IOChannel> ch_stdin, ch_stdout; > > > > std::vector<std::string> arguments; > > arguments.push_back("gnugo"); > > arguments.push_back("--mode"); > > arguments.push_back("gtp"); > > > > /spawn gnugo > > Glib::spawn_async_with_pipes(Glib::get_current_dir(), > > arguments,Glib::SPAWN_SEARCH_PATH, > > sigc::slot<void>(), > > &pid,&fd_stdin,&fd_stdout); > > > > //create the IOChannel from the file descriptors > > ch_stdin=Glib::IOChannel::create_from_fd(fd_stdin); > > ch_stdout=Glib::IOChannel::create_from_fd(fd_stdout); > > > > Glib::ustring input,output; > > > > //a stupid loop to test whether the pipes work > > while(true){ > > std::cin>>input; > > ch_stdin->write(input.append("\n")); > > ch_stdout->read_to_end(output); > > std::cout<<output<<std::endl; > > } > > } > > > > Any idea what I am doing wrong? > > > > Thanks! _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list