1

I have started to write a ruby module for the clang-c library.

I wrapp in my clang c module this

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

with a visitor like this:

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

and the ruby code (that is working) looks like this:

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

The idea is to take the block, pass it to the visitor as a parameter and call it in the visitor.

The C glue code looks like this:

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);
}

with the visitor (callback) :

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;
}

My answer is should I use rb_protect here?

The code can be found here :

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

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

cedlemo
  • 3,205
  • 3
  • 32
  • 50

1 Answers1

0

After some tests and after reading others people code, I have arrived to the conclusion that the usage of rb_protect to encapsulate the rb_funcall is not mandatory.

It should be used when you need to handle, in C, the possible exceptions in the ruby blocks or procs that are executed by rb_funcall.

I should mention that it must be more important to handle those exceptions when you embed ruby interpreter in C than when you write some C ruby extensions.

References :

cedlemo
  • 3,205
  • 3
  • 32
  • 50