Skip to content

Instantly share code, notes, and snippets.

@kersny
Created August 3, 2011 22:57
Show Gist options
  • Save kersny/1124069 to your computer and use it in GitHub Desktop.
Save kersny/1124069 to your computer and use it in GitHub Desktop.
Libuv bindings with static callbacks, no extra c layer, and magic numbers!
// Compile on Mac with Mono as 'dmcs PrepareWatcher.cs'
// With a libuv clone, after 'make', do:
// ar -x uv.a
// gcc -o libuv.dylib -dynamiclib -m32 *.o -framework CoreServices
// rm __.SYMDEF\ SORTED *.o
//
// Then run with 'mono PrepareWatcher.exe'
using System;
using System.Runtime.InteropServices;
namespace Libuv {
public class PrepareWatcher {
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void uv_prepare_cb(IntPtr prepare, int status);
[DllImport("uv")]
internal static extern int uv_prepare_init(IntPtr prepare);
[DllImport("uv")]
internal static extern int uv_prepare_start(IntPtr prepare, uv_prepare_cb cb);
[DllImport("uv")]
internal static extern int uv_prepare_stop(IntPtr prepare);
private static uv_prepare_cb unmanaged_callback;
static PrepareWatcher()
{
unmanaged_callback = StaticCallback;
}
private Action<int> callback;
private IntPtr _handle;
private GCHandle me;
public PrepareWatcher(Action<int> callback)
{
this._handle = Marshal.AllocHGlobal(64);
uv_prepare_init(this._handle);
var handle = (uv_handle_t)Marshal.PtrToStructure(this._handle, typeof(uv_handle_t));
this.me = GCHandle.Alloc(this, GCHandleType.Pinned);
handle.data = GCHandle.ToIntPtr(this.me);
this.callback = callback;
}
private static void StaticCallback(IntPtr watcher, int status)
{
var handle = (uv_handle_t)Marshal.PtrToStructure(watcher, typeof(uv_handle_t));
var instance = GCHandle.FromIntPtr(handle.data);
var watcher_instance = (PrepareWatcher)instance.Target;
watcher_instance.callback(status);
}
public void Start()
{
uv_prepare_start(this._handle, unmanaged_callback);
}
public void Stop()
{
uv_prepare_stop(this._handle);
}
~PrepareWatcher()
{
Cleanup();
}
private void Cleanup()
{
me.Free();
Marshal.FreeHGlobal(this._handle);
}
}
public struct uv_handle_t {
public uv_handle_type type;
public uv_close_cb close_cb;
public IntPtr data;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void uv_close_cb(IntPtr handle);
public enum uv_handle_type {
UV_UNKNOWN_HANDLE = 0,
UV_TCP,
UV_NAMED_PIPE,
UV_TTY,
UV_FILE,
UV_TIMER,
UV_PREPARE,
UV_CHECK,
UV_IDLE,
UV_ASYNC,
UV_ARES_TASK,
UV_ARES_EVENT,
UV_GETADDRINFO,
UV_PROCESS
}
public class MainClass {
[DllImport("uv")]
internal static extern int uv_init();
[DllImport("uv")]
internal static extern int uv_run();
public static void Main() {
uv_init();
PrepareWatcher prepare = new PrepareWatcher((status) => {
Console.WriteLine("Prepare Watcher Called");
});
prepare.Start();
uv_run();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment