Cannot get pipes to work with glibmm

View: New views
3 Messages — Rating Filter:   Alert me  

Cannot get pipes to work with glibmm

by Bastien Dalla Piazza :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

Re: Cannot get pipes to work with glibmm

by Bastien Dalla Piazza :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list

[SOLVED] Re: Cannot get pipes to work with glibmm

by Bastien Dalla Piazza :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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@...
http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list