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 descriptoras an input parameter and is used to create a new GIOChannel.Alternatively, the g_io_channel_new_file() API can be usedto create a channel for a file. Once the channel is created, it can be usedin 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() isused.
To set the position in the current GIOChannel, g_io_channel_seek_position() canbe 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 fileis used to create a GIOChannel, and then the contents ofthe 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 contentsof the file are read using g_io_channel_read_chars(), andthe 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; }
Using GIOChannel inGLib main loops
GIOChannel provides a wayto integrate file descriptors to main loops. The following code demonstratesthe usage. In the code, a pipe is created. A thread is created which writesto the write end of the pipe. The main loop checks if the other end of thepipe is ready to read. If it is, then the callback function is called. Thecallback calls g_main_loop_quit(), and the main loop is terminatedand 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; }