Created
August 3, 2011 22:57
-
-
Save kersny/1124069 to your computer and use it in GitHub Desktop.
Libuv bindings with static callbacks, no extra c layer, and magic numbers!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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