【问题标题】:how to rb_protect everything in ruby如何 rb_protect ruby​​ 中的所有内容
【发布时间】:2012-06-18 15:56:37
【问题描述】:

我想从我自己的 C 代码中调用 ruby​​ 代码。万一出现异常,我必须 rb_protect 我调用的 ruby​​ 代码。 rb_protect 看起来像这样:

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

所以proc 必须是一个接受VALUE 参数并返回VALUE 的函数。我必须调用很多不能以这种方式工作的函数。我怎样才能rb_protect他们不引发异常?

我曾想过使用Data_Make_Struct 将所有内容包装到一个ruby 对象中并在其上调用方法。 Data_Make_Struct 本身可能引发异常。我怎么rb_protectData_Make_Struct

【问题讨论】:

    标签: ruby ruby-c-extension


    【解决方案1】:

    要以灵活的方式使用 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_rescuerb_ensure 可能是解决某些问题的更好方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-08
      • 1970-01-01
      • 1970-01-01
      • 2013-03-20
      • 2011-10-14
      • 1970-01-01
      • 2011-10-14
      • 2019-12-21
      相关资源
      最近更新 更多