要rb_protect
以灵活的方式使用(例如,使用任意数量的参数调用 Ruby 函数),请将一个小的调度函数传递给rb_protect
. Ruby 需要sizeof(VALUE) == sizeof(void*)
,并且rb_protect
盲目地将VALUE
-typed 数据传递给 dispatch 函数,而不检查或修改它。这意味着您可以将所需的任何数据传递给调度函数,让它解包数据并调用适当的 Ruby 方法。
例如,要rb_protect
调用 Ruby 方法,您可能会使用如下内容:
#define MAX_ARGS 16
struct my_callback_stuff {
VALUE obj;
ID method_id;
int nargs;
VALUE args[MAX_ARGS];
};
VALUE my_callback_dispatch(VALUE rdata)
{
struct my_callback_stuff* data = (struct my_callback_stuff*) rdata;
return rb_funcall2(data->obj, data->method_id, data->nargs, data->args);
}
... in some other function ...
{
/* need to call Ruby */
struct my_callback_stuff stuff;
stuff.obj = the_object_to_call;
stuff.method_id = rb_intern("the_method_id");
stuff.nargs = 3;
stuff.args[0] = INT2FIX(1);
stuff.args[1] = INT2FIX(2);
stuff.args[2] = INT2FIX(3);
int state = 0;
VALUE ret = rb_protect(my_callback_dispatch, (VALUE)(&stuff), &state);
if (state) {
/* ... error processing happens here ... */
}
}
另外,请记住,rb_rescue
或者rb_ensure
可能是解决某些问题的更好方法。