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/