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::RefPtrGlib::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::coutbuf;
return true;
}
int main(int argc, char** argv)
{
Gtk::Main kit(argc,argv);
int fd_stdout, fd_stdin;
Glib::Pid pid;
std::vectorstd::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::slotvoid(),
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::slotbool,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::RefPtrGlib::IOChannel ch_stdin, ch_stdout;
std::vectorstd::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::slotvoid(),
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