On Thu, Aug 26, 2010 at 11:01 AM, Hrvoje Niksic <hrvoje.niksic@xxxxxxx> wrote:
#include <glib.h>
enum {READFD, WRITEFD, TTLPIPEFDS};
int fd[TTLPIPEFDS];
gboolean my_callback(GIOChannel *source, GIOCondition condition, gpointer data)
{
switch (condition)
{
The good news is that libraries shouldn't require a terminal for stdout because then they wouldn't work with stdout being redirected to a file (highly unlikely).
The bad news is that this is harder to do correctly than it sounds. If you connect stdout to a pipe, then a thread (or a subprocess) should exist to collect output from the pipe, or the program deadlocks whenever a library prints a chunk of output larger than the pipe buffer.
The other bad news is that the dup2/pipe solution is very Unix-specific. It is not clear if this is a problem to Richard.
Hi guys,
Thanks for the feedback, I'm now sorted.
You are correct, the libraries don't expect a terminal, no problem there.
The actual program I intend to use this in is a background process where the actual processing executes in a separate thread while the main thread sits in the main loop. With the watch on the read-end of the pipe, the callback is fired and executes within the main loop, while all writing occurs on the execution thread; i.e, backwards from what you suggest, but both processing entities (write to, read from) are separate and so can't collide with or block each other (he says, crossing fingers furiously).
I re-post the modified code, very pared down, using GIOChannel watching that now works as expected/required.
thanks again,
richard
==== BEGIN CODE =====
// save to: io.c
// compile as: gcc io.c `pkg-config --cflags --libs glib-2.0`
#include <stdio.h>
#include <string.h>
enum {READFD, WRITEFD, TTLPIPEFDS};
int fd[TTLPIPEFDS];
gboolean my_callback(GIOChannel *source, GIOCondition condition, gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
switch (condition)
{
case G_IO_IN:
{
gchar buf2[100];
memset(buf2, 0, sizeof(buf2));
read(fd[READFD], buf2, sizeof(buf2)); // read the data from the read-end of the pipe
if (buf2[0])
fprintf(stderr, "written to file: '%s'\n", buf2);
if (buf2[0])
{ // output to text file and to stderr
FILE *fp = fopen("/tmp/test.out", "w+");
fprintf(fp, "%s", buf2);
fclose(fp);
fprintf(stderr, "written to file: '%s'\n", buf2);
}
g_main_loop_quit(loop);
g_io_channel_shutdown(source,TRUE,NULL);
g_io_channel_shutdown(source,TRUE,NULL);
}
break;
}
}
gboolean idle_function(gpointer nil)
{
return FALSE; // remove
}
int main()
GMainLoop *loop = g_main_loop_new(NULL,FALSE);
GIOChannel *channel;
if (pipe(fd) < 0) return(-1); // make a new pipe
break;
}
return FALSE;
}
gboolean idle_function(gpointer nil)
{
printf("printf() test" );
fflush(stdout);
return FALSE; // remove
}
int main()
{
GMainLoop *loop = g_main_loop_new(NULL,FALSE);
GIOChannel *channel;
if (pipe(fd) < 0) return(-1); // make a new pipe
if (dup2(fd[WRITEFD], fileno(stdout)) < 0) return(-1); // copy stdout to write-end
close(fd[WRITEFD]);
g_idle_add((GSourceFunc) idle_function, NULL); // write message to stdout
g_main_loop_run(loop);
}
g_idle_add((GSourceFunc) idle_function, NULL); // write message to stdout
channel = g_io_channel_unix_new(fd[READFD]); // watch read-end of pipe
g_io_add_watch(channel, G_IO_IN,(GIOFunc) my_callback, loop);
g_main_loop_run(loop);
return 0;
}
==== END CODE =====
_______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list