Like rb_protect everything in ruby

I want to call ruby ​​code from my own C code. In case of an exception, I have to rb_protect the ruby ​​code that I call. rb_protect looks like this:

VALUE rb_protect(VALUE (* proc) (VALUE), VALUE data, int * state) 

So proc should be a function that takes VALUE arguments and returns VALUE . I have to name a lot of functions that do not work. How can rb_protect from them create exceptions?

I thought about using Data_Make_Struct to wrap everything in one ruby ​​object and call methods on it. Data_Make_Struct may itself throw an exception. How do I rb_protect Data_Make_Struct ?

+6
source share
1 answer

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 ... { /* 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 ... */ } } 

Also, keep in mind that rb_rescue or rb_ensure may be the best approach for some problems.

+4
source

Source: https://habr.com/ru/post/918379/


All Articles