ただrubyの時の様にalloc_funcが無いのでinitializeでメンバに放り込んでる。
まぁしょうがないか。
#include <mruby.h>
#include <mruby/proc.h>
#include <mruby/data.h>
#include <compile.h>
#include <variable.h>
#include <uv.h>
typedef struct {
mrb_state* mrb;
mrb_value proc;
void* data;
} mrb_uv_data;
static void
uv_handle_free(mrb_state *mrb, void *p)
{
uv_close((uv_handle_t*) ((mrb_uv_data*)p)->data, NULL);
free(((mrb_uv_data*)p)->data);
}
static const struct mrb_data_type uv_handle_data_type = {
"uv_handle", uv_handle_free,
};
static mrb_value
mrb_uv_run(mrb_state *mrb, mrb_value self)
{
return mrb_fixnum_value(uv_run(uv_default_loop()));
}
static mrb_value
mrb_uv_timer_init(mrb_state *mrb, mrb_value self)
{
mrb_uv_data* uvdata = (mrb_uv_data*) malloc(sizeof(mrb_uv_data));
uvdata->mrb = mrb;
uvdata->data = malloc(sizeof(uv_timer_t));
uvdata->proc = mrb_nil_value();
uv_timer_init(uv_default_loop(), (uv_timer_t*) uvdata->data);
mrb_iv_set(mrb, self, mrb_intern(mrb, "data"), mrb_obj_value(
Data_Wrap_Struct(mrb, (struct RClass*) &self,
&uv_handle_data_type, (void*) uvdata)));
return self;
}
void
_uv_timer_cb(uv_timer_t* timer, int status) {
mrb_uv_data* uvdata = (mrb_uv_data*) timer->data;
mrb_yield(uvdata->mrb, uvdata->proc, mrb_fixnum_value(status));
}
static mrb_value
mrb_uv_timer_start(mrb_state *mrb, mrb_value self) {
mrb_value value;
mrb_uv_data* uvdata;
struct RProc *b;
mrb_value argc, *argv;
int nargs;
mrb_get_args(mrb, "b*", &b, &argv, &argc);
if (mrb_fixnum(argc) != 2) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "too few arguments");
}
value = mrb_iv_get(mrb, self, mrb_intern(mrb, "data"));
Data_Get_Struct(mrb, value, &uv_handle_data_type, uvdata);
uvdata->proc = mrb_obj_value(b);
((uv_timer_t*) uvdata->data)->data = uvdata;
uv_timer_start((uv_timer_t*) uvdata->data, _uv_timer_cb,
mrb_fixnum(argv[0]),
mrb_fixnum(argv[1]));
return mrb_nil_value();
}
int
main() {
int n;
mrb_state* mrb;
struct mrb_parser_state* st;
struct RClass *uv, *uv_timer;
mrb = mrb_open();
uv = mrb_define_module(mrb, "UV");
mrb_define_class_method(mrb, uv, "run", mrb_uv_run, ARGS_REQ(1));
uv_timer = mrb_define_class_under(mrb, uv, "Timer", mrb_class_obj_get(mrb, "Object"));
mrb_define_method(mrb, uv_timer, "initialize", mrb_uv_timer_init, ARGS_ANY());
mrb_define_method(mrb, uv_timer, "start", mrb_uv_timer_start, ARGS_ANY());
{
char* code =
"require 'UV' \n"
"t = UV::Timer.new() \n"
"t.start(1000, 1000) {|x| \n"
" p x \n"
"} \n"
"p UV.run() \n";
st = mrb_parse_string(mrb, code);
n = mrb_generate_code(mrb, st->tree);
mrb_pool_close(st->pool);
mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_nil_value());
}
}
/* vim:set et ts=2 sts=2 sw=2 tw=0: */
実行するとrubyのコード
require 'UV'
t = UV::Timer.new()
t.start(1000, 1000) {|x|
p x
}
p UV.run()
の通り、1秒間隔で1秒後に再発動するタイマ、つまりは1秒おきにステータスが表示される。この辺の引数はUVと合わせた。エラーチェックとかサボリまくってるのでお手本のコードにはならない。
. .: : : : : : : : :: :::: :: :: : :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
. . : : : :: : : :: : ::: :: : :::: :: ::: ::: ::::::::::::::::::::::::::::::::::::::
. . .... ..: : :: :: :: :: :: :: .。oO(寿司食べたい…):::::::
Λ_Λ . . . .: : : ::: : :: ::::::::: :::::::::::::::::::::::::::::
/:彡ミ゛ヽ;)ー、 . . .: : : :::::: :::::::::::::::::::::::::::::::::
/ :::/:: ヽ、ヽ、 ::i . .:: :.: ::: . :::::::::::::::::::::::::::::::::::::::
/ :::/;;: ヽ ヽ ::l . :. :. .:: : :: :: :::::::: : ::::::::::::::::::
 ̄ ̄ ̄(_,ノ  ̄ ̄ ̄ヽ、_ノ ̄ ̄ ̄ ̄
. . : : : :: : : :: : ::: :: : :::: :: ::: ::: ::::::::::::::::::::::::::::::::::::::
. . .... ..: : :: :: :: :: :: :: .。oO(寿司食べたい…):::::::
Λ_Λ . . . .: : : ::: : :: ::::::::: :::::::::::::::::::::::::::::
/:彡ミ゛ヽ;)ー、 . . .: : : :::::: :::::::::::::::::::::::::::::::::
/ :::/:: ヽ、ヽ、 ::i . .:: :.: ::: . :::::::::::::::::::::::::::::::::::::::
/ :::/;;: ヽ ヽ ::l . :. :. .:: : :: :: :::::::: : ::::::::::::::::::
 ̄ ̄ ̄(_,ノ  ̄ ̄ ̄ヽ、_ノ ̄ ̄ ̄ ̄
あとは適当にゆっくりやっときます。
mattn/mruby-uv - GitHub
inteface to libuv for mruby
https://github.com/mattn/mruby-uv