柔軟な方法で使用するrb_protect
には(たとえば、任意の数の引数を使用してRuby関数を呼び出す)、小さなディスパッチ関数をに渡しますrb_protect
。Rubyはそれを要求しsizeof(VALUE) == sizeof(void*)
、タイプされたデータを検査したり変更したりせずに、rb_protect
盲目的VALUE
にディスパッチ関数に渡します。これは、必要なデータをディスパッチ関数に渡し、データを解凍して適切な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
がより良いアプローチである可能性があることを覚えておいてください。