【问题标题】:Is the usage of rb_protect mandatory when we use rb_funcall当我们使用 rb_funcall 时是否必须使用 rb_protect
【发布时间】:2016-04-02 09:32:46
【问题描述】:

我已经开始为 clang-c 库写一个 ruby​​ 模块了。

我把这个包装在我的clang c模块中

unsigned clang_visitChildren(CXCursor parent,
                             CXCursorVisitor visitor,
                             CXClientData client_data);

有这样的访客:

typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor,
                                                   CXCursor parent,
                                                   CXClientData client_data);

并且 ruby​​ 代码(正在运行)如下所示:

Clangc.visit_children(cursor: tu.cursor) do |cursor, parent| 
  puts cursor
  puts parent
  Clangc::ChildVisitResult::RECURSE  
end

思路是取block,作为参数传给visitor,在visitor中调用。

C 粘合代码如下所示:

VALUE
m_clangc_visit_children_with_proc(VALUE self, VALUE cursor, VALUE aproc)
{
    if (rb_class_of(aproc) != rb_cProc) rb_raise(rb_eTypeError, "Need a block");

    VALUE callback = aproc;
    Cursor_t *c;
    unsigned ret_with_break;

    Data_Get_Struct(cursor, Cursor_t, c);
    ret_with_break = clang_visitChildren(c->data,
                                         visitor,
                                         (CXClientData) callback);
    /*return false if ret_with_break == 0*/
    return NOT_0_2_RVAL(ret_with_break);
}

与访客(回调):

static enum CXChildVisitResult
visitor(CXCursor cursor, CXCursor parent, CXClientData client_data)
{
    /*basic variables initialization...*/
    r_ret = rb_funcall(callback, rb_intern("call"), 2, r_cursor, r_parent);

    if (TYPE(r_ret) == T_FIXNUM)
    {
        ret = NUM2UINT(r_ret);
        if (ret == CXChildVisit_Break || ret == CXChildVisit_Continue ||
            ret == CXChildVisit_Recurse)
            return ret;
        else
            return CXChildVisit_Break;
    }
    else
        return CXChildVisit_Break;
}

我的回答是我应该在这里使用 rb_protect 吗?

代码可以在这里找到:

https://github.com/cedlemo/ruby-clangc/blob/master/ext/clangc/_clangc_functions.c#L146

https://github.com/cedlemo/ruby-clangc/

【问题讨论】:

    标签: ruby clang ruby-c-extension


    【解决方案1】:

    经过一些测试和阅读其他人的代码,我得出结论,使用rb_protect 来封装rb_funcall 不是强制性的。

    当您需要在 C 中处理 rb_funcall 执行的 ruby​​ 块或 procs 中可能出现的异常时,应该使用它。

    我应该提到,在 C 中嵌入 ruby​​ 解释器时处理这些异常肯定比编写一些 C ruby​​ 扩展时更重要。

    参考资料:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-29
      • 1970-01-01
      • 1970-01-01
      • 2011-09-17
      • 2022-11-14
      • 2017-11-05
      相关资源
      最近更新 更多