2016-04-02 3 views
1

Ich habe begonnen, ein Ruby-Modul für die clang-c-Bibliothek zu schreiben.Ist die Verwendung von rb_protect obligatorisch, wenn wir rb_funcall verwenden

ich in meinem Klirren c Modul Wrapp diese

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

mit einem Besucher wie folgt aus:

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

und dem Ruby-Code (das funktioniert) sieht wie folgt aus:

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

Die Idee ist, den Block zu nehmen, ihn dem Besucher als Parameter zu übergeben und ihn im Besucher zu nennen.

Der C Glue-Code sieht wie folgt aus:

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

mit dem Besucher (Rückruf):

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

Meine Antwort ist, sollte ich rb_protect hier benutzen?

Der Code kann hier gefunden werden:

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

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

Antwort

0

Nach einigen Tests und nach anderen Menschen Code lesen, ich bin zu dem Schluss gekommen, dass die Nutzung von rb_protect die rb_funcall einzukapseln ist nicht zwingend erforderlich.

Es sollte verwendet werden, wenn Sie in C die möglichen Ausnahmen in den Ruby-Blöcken oder -Procs behandeln müssen, die von rb_funcall ausgeführt werden.

Ich sollte erwähnen, dass es wichtiger sein muss, diese Ausnahmen zu behandeln, wenn Sie Ruby-Interpreter in C einbetten als wenn Sie einige C Ruby-Erweiterungen schreiben.

Referenzen:

Verwandte Themen