To use rb_protect
flexible way (for example, to call the Ruby function with an arbitrary number of arguments), pass the small dispatch function rb_protect
. Ruby requires that sizeof(VALUE) == sizeof(void*)
and rb_protect
blindly pass VALUE
data to the send function without checking or changing. This means that you can transfer any data you want for the send function, allow them to unpack the data, and call the appropriate Ruby methods.
For example, to rb_protect
call the Ruby method, you can use something like this:
#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 ... { 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) { } }
Also, keep in mind that rb_rescue
or rb_ensure
may be the best approach for some problems.
source share