GIOChannel
GIOChannel provides a portable method for using file descriptors, sockets and pipes and integrating them into the GLib main loop.
The g_io_channel_unix_new()
API takes a file descriptor
as an input parameter and is used to create a new GIOChannel
.
Alternatively, the g_io_channel_new_file()
API can be used
to create a channel for a file. Once the channel is created, it can be used
in a generic manner.
To read a channel, APIs such as the following can be used:
g_io_channel_read_chars()
g_io_channel_read_line()
g_io_channel_read_to_end()
To write to a channel an API like g_io_channel_write_chars()
is
used.
To set the position in the current GIOChannel
, g_io_channel_seek_position()
can
be used.
Finally the channel can be closed using g_io_channel_shutdown()
.
The following is an example code where a file descriptor to a plain file
is used to create a GIOChannel
, and then the contents of
the file are read in chunks of 100 bytes and printed using g_print
.
Finally the channel is closed.
#include <glib.h> #include <stdio.h> int main(int argc, char *argv[]) { GIOChannel *channel; gchar buf[100]; gsize bytes_read; FILE *fp; if(argc != 2) { g_print("usage:cat <file_name>\n"); g_print("Press any key to exit\n"); getchar(); return 1; } fp = fopen(argv[1],"r"); if(!fp) { g_print("Unable to open the file %s\n",argv[1]); return 1; } channel = g_io_channel_unix_new(fileno(fp)); do { g_io_channel_read_chars(channel,buf,100,&bytes_read,NULL); g_print("%s",buf); } while(bytes_read > 0); g_io_channel_shutdown(channel,TRUE,NULL); fclose(fp); return 0; }
In the example below, a sample code to copy a file is written. In the code,
channels are opened using g_io_channel_new_file()
. The contents
of the file are read using g_io_channel_read_chars()
, and
the contents are written to a new file using g_io_channel_write_chars()
.
#include <glib.h> #include <stdio.h> int main(int argc, char *argv[]) { GIOChannel *in_channel,*out_channel; gchar buf[100]; gsize bytes_read,bytes_written; GError *error = NULL; if(argc != 3) { g_print("usage:<cp SOURCE> <DESTINATION>\n"); g_print("Press any key to exit\n"); getchar(); return 1; } in_channel = g_io_channel_new_file(argv[1],"r",&error); if(!in_channel) { g_print("Unable to open the file %s to read\n",argv[1]); g_print("Press any key to exit\n"); getchar(); return 1; } out_channel = g_io_channel_new_file(argv[2],"w",&error); if(!out_channel) { g_print("Unable to open the file %s to write\n",argv[2]); g_print("Press any key to exit\n"); getchar(); return 1; } do { g_io_channel_read_chars(in_channel,buf,100,&bytes_read,&error); if(error) { g_print("Error while reading file %s\n",argv[1]); g_print("Press any key to exit\n"); getchar(); return 1; } g_io_channel_write_chars(out_channel,buf,bytes_read,&bytes_written,&error); if(error) { g_print("Error while writing file %s\n",argv[2]); g_print("Press any key to exit\n"); getchar(); return 1; } } while(bytes_read > 0); g_io_channel_shutdown(in_channel,TRUE,&error); if(error) { g_print("Error has occured\n"); g_print("Press any key to exit\n"); getchar(); return 1; } g_io_channel_shutdown(out_channel,TRUE,&error); if(error) { g_print("Error has occured\n"); g_print("Press any key to exit\n"); getchar(); return 1; } g_print("File copied successfully...\n"); getchar(); return 0; }
GIOChannel
in
GLib main loopsGIOChannel
provides a way
to integrate file descriptors to main loops. The following code demonstrates
the usage. In the code, a pipe is created. A thread is created which writes
to the write end of the pipe. The main loop checks if the other end of the
pipe is ready to read. If it is, then the callback function is called. The
callback calls g_main_loop_quit()
, and the main loop is terminated
and g_main_loop_run()
returns.
#include <glib.h> #include <stdio.h> int fd[2]; void *thread_function(void *data) { // call sleep so that the main loop source is not ready immediately sleep(10); write(fd[1],"GIOChannel main loop example",29); return NULL; } gboolean my_callback(GIOChannel *source,GIOCondition condition,gpointer data) { char buf[100]; read(fd[0],buf,sizeof(buf)); g_print("%s",buf); getchar(); g_main_loop_quit((GMainLoop *)data); return FALSE; } int main() { GMainLoop *loop; GIOChannel *channel; pipe(fd); channel = g_io_channel_unix_new(fd[0]); g_thread_init(NULL); g_thread_create(thread_function,NULL,TRUE,NULL); loop = g_main_loop_new(NULL,FALSE); g_io_add_watch(channel,G_IO_IN | G_IO_HUP | G_IO_ERR,(GIOFunc)my_callback,loop); g_main_loop_run(loop); g_io_channel_shutdown(channel,TRUE,NULL); return 0; }