Monday, November 12, 2007

IOChannels and Spawning

For the most part, we like to avoid wrapping as much of glib as possible, instead preferring the .Net framework capabilities. We hide as many GList and GHashtable parameters as possible, for example.

I've received several comments in the past that the .Net APIs for IO and process spawning didn't really match up to the glib API. Taking this feedback, I spent the last couple days wrapping, testing, and documenting a new glib-sharp binding for g_spawn_* and GIOChannel.

Here's an example usage from the docs:

using GLib;
using System;

public class SpawnTest {

public static void Main (string[] args)
{
new SpawnTest ();
}

MainLoop main_loop;
IOChannel channel;

public SpawnTest ()
{
main_loop = new MainLoop ();

try {
Process proc;
int stdin = Process.IgnorePipe;
int stdout = Process.RequestPipe;
int stderr = Process.IgnorePipe;
GLib.Process.SpawnAsyncWithPipes (null, new string[] {"pwd"}, null,
SpawnFlags.SearchPath, null,
out proc, ref stdin, ref stdout,
ref stderr);
channel = new IOChannel (stdout);
channel.AddWatch (0, IOCondition.In | IOCondition.Hup, new IOFunc (ReadStdout));
} catch (Exception e) {
Console.WriteLine ("Exception in Spawn: " + e);
}

main_loop.Run ();
}

bool ReadStdout (IOChannel source, IOCondition condition)
{
if ((condition & IOCondition.In) == IOCondition.In) {
string txt;
if (source.ReadToEnd (out txt) == IOStatus.Normal)
Console.WriteLine ("[SpawnTest output] " + txt);
}
if ((condition & IOCondition.Hup) == IOCondition.Hup) {
source.Dispose ();
main_loop.Quit ();
return true;
}
return true;
}
}

I'd appreciate it if anyone who has been missing this functionality in Gtk# would try it out and let me know any issues you find, or places the API can be improved.