win32fiber(失敗)

WindowsのFiberでcoroutineを作れないかと思ったものの、案の定、失敗。
動かないソースだけ貼り付けとく。

#include <windows.h>
#include "ruby.h"

static VALUE Fiber;
static VALUE FiberError;

struct win32fiber {
  LPVOID main_fiber;
  LPVOID fiber;
  VALUE proc;
};

static void rb_win32fiber_mark(struct win32fiber *p) {
  if (!NIL_P(p->proc)) {
    rb_gc_mark(p->proc);
  }

  xfree(p);
}

static void rb_win32fiber_free(struct win32fiber *p) {
  if (p->fiber) {
    DeleteFiber(p->fiber);
  }

  xfree(p);
}

static VALUE rb_win32fiber_alloc(VALUE klass) {
  struct win32fiber *p;

  p = ALLOC(struct win32fiber);
  p->main_fiber = NULL;
  p->fiber      = NULL;
  p->proc       = Qnil;

  return Data_Wrap_Struct(klass, rb_win32fiber_mark, rb_win32fiber_free, p);
}

static VALUE corutine_proc_call(VALUE proc) {
  return rb_funcall(proc, rb_intern("call"), 0);
}

static VALUE corutine_yield(VALUE data1, VALUE data2, VALUE self) {
  struct win32fiber *p = (struct win32fiber *) data2;
  SwitchToFiber(p->main_fiber);
  return Qnil;
}

static void _stdcall corutine(LPVOID param) {
  struct win32fiber *p = (struct win32fiber *) param;
  rb_iterate(corutine_proc_call, p->proc, corutine_yield, (VALUE) p);
}

static VALUE rb_win32fiber_initialize(VALUE self) {
  struct win32fiber *p;

  rb_need_block();

  Data_Get_Struct(self, struct win32fiber, p);
  p->main_fiber = ConvertThreadToFiber(NULL);

  if (p->main_fiber == NULL) {
    rb_raise(FiberError, "ConvertThreadToFiber failed: %d", GetLastError());
  }

  p->fiber = CreateFiber(0, corutine, (LPVOID) p);

  if (p->fiber == NULL) {
    rb_raise(FiberError, "CreateFiber failed: %d", GetLastError());
  }

  p->proc = rb_block_proc();

  return Qnil;
}

static VALUE rb_win32fiber_resume(VALUE self) {
  struct win32fiber *p;
  Data_Get_Struct(self, struct win32fiber, p);
  SwitchToFiber(p->fiber);
  return Qnil;
}

__declspec(dllexport)
void Init_win32fiber() {
  Fiber = rb_define_class("Fiber", rb_cObject);
  FiberError = rb_define_class_under(Fiber, "Error", rb_eStandardError);

  rb_define_alloc_func(Fiber, rb_win32fiber_alloc);
  rb_define_private_method(Fiber, "initialize", rb_win32fiber_initialize, 0);
  rb_define_method(Fiber, "resume", rb_win32fiber_resume, 0);
}
require 'win32fiber'

fiber = Fiber.new do
  loop do
    puts ""
    yield
    puts ""
    yield
    puts ""
    yield
    puts ""
    yield
  end
end

loop do
  while gets
    fiber.resume
  end
end