diff --git a/src/gevent/_ffi/watcher.py b/src/gevent/_ffi/watcher.py
index 76bbcdc511c3461230dd5712154300c0cac5a9ab..44d6353adb0abd32e1f8a2c55de6b28705c65ae1 100644
--- a/src/gevent/_ffi/watcher.py
+++ b/src/gevent/_ffi/watcher.py
@@ -57,13 +57,14 @@ class AbstractWatcherType(type):
 
     @classmethod
     def _fill_watcher(cls, name, bases, cls_dict):
-        def _mro_get(attr, bases):
+        def _mro_get(attr, bases, error=True):
             for b in bases:
                 try:
                     return getattr(b, attr)
                 except AttributeError:
                     continue
-            raise AttributeError(attr)
+            if error:
+                raise AttributeError(attr)
         _watcher_prefix = cls_dict.get('_watcher_prefix') or _mro_get('_watcher_prefix', bases)
 
         if '_watcher_type' not in cls_dict:
@@ -80,12 +81,19 @@ class AbstractWatcherType(type):
 
         LazyOnClass.lazy(cls_dict, _watcher_is_active)
 
+        watcher_struct_pattern = (cls_dict.get('_watcher_struct_pattern')
+                                  or _mro_get('_watcher_struct_pattern', bases, False)
+                                  or 'struct %s')
+        watcher_struct_name = watcher_struct_pattern % (watcher_type,)
+
         def _watcher_struct_pointer_type(self):
-            return self._FFI.typeof('struct ' + self._watcher_type + '*')
+            return self._FFI.typeof(watcher_struct_name + ' *')
 
         LazyOnClass.lazy(cls_dict, _watcher_struct_pointer_type)
 
-        callback_name = cls_dict.get('watcher_callback_name', '_gevent_generic_callback')
+        callback_name = (cls_dict.get('_watcher_callback_name')
+                         or _mro_get('_watcher_callback_name', bases, False)
+                         or '_gevent_generic_callback')
 
         def _watcher_callback(self):
             return self._FFI.addressof(self._LIB, callback_name)
@@ -147,6 +155,9 @@ class watcher(object):
     def _watcher_ffi_start(self):
         raise NotImplementedError()
 
+    def _watcher_ffi_stop(self):
+        self._watcher_stop(self.loop._ptr, self._watcher)
+
     def _watcher_ffi_ref(self):
         raise NotImplementedError()
 
@@ -238,7 +249,7 @@ class watcher(object):
 
     def stop(self):
         self._watcher_ffi_ref()
-        self._watcher_stop(self.loop._ptr, self._watcher)
+        self._watcher_ffi_stop()
         self.loop._keepaliveset.discard(self)
 
         self.callback = None
@@ -263,18 +274,29 @@ class watcher(object):
 
 watcher = AbstractWatcherType('watcher', (object,), dict(watcher.__dict__))
 
+import functools
+
+def not_while_active(func):
+    @functools.wraps(func)
+    def nw(self, *args, **kwargs):
+        if self.active:
+            raise AttributeError("not while active")
+        func(self, *args, **kwargs)
+    return nw
+
 class IoMixin(object):
 
     EVENT_MASK = 0
 
-    def __init__(self, loop, fd, events, ref=True, priority=None):
+    def __init__(self, loop, fd, events, ref=True, priority=None, _args=None):
         # XXX: Win32: Need to vfd_open the fd and free the old one?
         # XXX: Win32: Need a destructor to free the old fd?
         if fd < 0:
             raise ValueError('fd must be non-negative: %r' % fd)
         if events & ~self.EVENT_MASK:
             raise ValueError('illegal event mask: %r' % events)
-        super(IoMixin, self).__init__(loop, ref=ref, priority=priority, args=(fd, events))
+        super(IoMixin, self).__init__(loop, ref=ref, priority=priority,
+                                      args=_args or (fd, events))
 
     def start(self, callback, *args, **kwargs):
         args = args or _NOARGS
diff --git a/src/gevent/core.py b/src/gevent/core.py
index 5019974440180e552f9389470940ee3ef3c68f1f..07a0c8822007c82218541cc63a6fadc1a721b0f0 100644
--- a/src/gevent/core.py
+++ b/src/gevent/core.py
@@ -15,7 +15,12 @@ except ImportError:
         raise
 
     # CFFI/PyPy
-    from gevent.libev import corecffi as _core
+    lib = os.environ.get('GEVENT_CORE_CFFI_ONLY')
+    if lib == 'libuv':
+        from gevent.libuv import loop as _core
+    else:
+        from gevent.libev import corecffi as _core
+
 
 copy_globals(_core, globals())
 
diff --git a/src/gevent/libuv/_corecffi_cdef.c b/src/gevent/libuv/_corecffi_cdef.c
index 3d03d8741c1af98ed75cb8ddeafa7ae4bc0a58cf..5e9c28fe3176b49781c6a7b5a415186fb7872067 100644
--- a/src/gevent/libuv/_corecffi_cdef.c
+++ b/src/gevent/libuv/_corecffi_cdef.c
@@ -113,24 +113,24 @@ typedef struct uv_fs_poll_s uv_fs_poll_t;
 
 
 // callbacks with the same signature
-typedef void (*uv_close_cb)(uv_handle_t *handle);
-typedef void (*uv_idle_cb)(uv_idle_t *handle);
-typedef void (*uv_timer_cb)(uv_timer_t *handle);
-typedef void (*uv_check_cb)(uv_check_t* handle);
-typedef void (*uv_async_cb)(uv_async_t* handle);
-typedef void (*uv_prepare_cb)(uv_prepare_t *handle);
+typedef void (*uv_close_cb)(void *handle);
+typedef void (*uv_idle_cb)(void *handle);
+typedef void (*uv_timer_cb)(void *handle);
+typedef void (*uv_check_cb)(void* handle);
+typedef void (*uv_async_cb)(void* handle);
+typedef void (*uv_prepare_cb)(void*handle);
 
 // callbacks with distinct sigs
-typedef void (*uv_walk_cb)(uv_handle_t *handle, void *arg);
-typedef void (*uv_poll_cb)(uv_poll_t *handle, int status, int events);
-typedef void (*uv_signal_cb)(uv_signal_t *handle, int signum);
+typedef void (*uv_walk_cb)(void *handle, void *arg);
+typedef void (*uv_poll_cb)(void *handle, int status, int events);
+typedef void (*uv_signal_cb)(void *handle, int signum);
 
 // Callback passed to uv_fs_event_start() which will be called
 // repeatedly after the handle is started. If the handle was started
 // with a directory the filename parameter will be a relative path to
 // a file contained in the directory. The events parameter is an ORed
 // mask of uv_fs_event elements.
-typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename, int events, int status);
+typedef void (*uv_fs_event_cb)(void* handle, const char* filename, int events, int status);
 
 typedef struct {
     long tv_sec;
@@ -288,10 +288,10 @@ static void (*gevent_noop)(void* handle);
  * watcher types has a 'void* data' that stores the CFFI handle to the Python watcher
  * object.
  */
-static void _gevent_generic_callback0(uv_handle_t* handle); // no extra args
-static void _gevent_generic_callback1(uv_handle_t* handle, int arg); // one extra args. Everything will funnel through this
-static void _gevent_poll_callback2(uv_handle_t* handle, int status, int events);
-static void _gevent_fs_event_callback3(uv_handle_t* handle, const char* filename, int events, int status);
+static void _gevent_generic_callback0(void* handle); // no extra args
+static void _gevent_generic_callback1(void* handle, int arg); // one extra args. Everything will funnel through this
+static void _gevent_poll_callback2(void* handle, int status, int events);
+static void _gevent_fs_event_callback3(void* handle, const char* filename, int events, int status);
 
 typedef struct _gevent_fs_poll_s {
 	uv_fs_poll_t handle;
diff --git a/src/gevent/libuv/_corecffi_source.c b/src/gevent/libuv/_corecffi_source.c
index 27214a6db207d6b10a38b2b99f0fc8aac7ccf95e..5228cfd936d7910c0461ae60080930450efe5268 100644
--- a/src/gevent/libuv/_corecffi_source.c
+++ b/src/gevent/libuv/_corecffi_source.c
@@ -8,8 +8,9 @@ static void _gevent_noop(void*handle) {}
 
 static void (*gevent_noop)(void* handle) = &_gevent_noop;
 
-static void _gevent_generic_callback1(uv_handle_t* watcher, int arg)
+static void _gevent_generic_callback1(void* vwatcher, int arg)
 {
+	uv_handle_t* watcher = (uv_handle_t*)vwatcher;
     void* handle = watcher->data;
     int cb_result = python_callback(handle, arg);
     switch(cb_result) {
@@ -34,17 +35,17 @@ static void _gevent_generic_callback1(uv_handle_t* watcher, int arg)
 }
 
 
-static void _gevent_generic_callback0(uv_handle_t* handle)
+static void _gevent_generic_callback0(void* handle)
 {
 	_gevent_generic_callback1(handle, 0);
 }
 
-static void _gevent_poll_callback2(uv_handle_t* handle, int status, int events)
+static void _gevent_poll_callback2(void* handle, int status, int events)
 {
 	_gevent_generic_callback1(handle, status < 0 ? status : events);
 }
 
-static void _gevent_fs_event_callback3(uv_handle_t* handle, const char* filename, int events, int status)
+static void _gevent_fs_event_callback3(void* handle, const char* filename, int events, int status)
 {
 	_gevent_generic_callback1(handle, status < 0 ? status : events);
 }