mrb_value mrb_class_find_path(mrb_state *mrb, struct RClass *c) { struct RClass *outer; mrb_value path; mrb_sym name; const char *str; mrb_int len; if (detect_outer_loop(mrb, c)) return mrb_nil_value(); outer = outer_class(mrb, c); if (outer == NULL) return mrb_nil_value(); name = find_class_sym(mrb, outer, c); if (name == 0) return mrb_nil_value(); str = mrb_class_name(mrb, outer); path = mrb_str_new_capa(mrb, 40); mrb_str_cat_cstr(mrb, path, str); mrb_str_cat_cstr(mrb, path, "::"); str = mrb_sym2name_len(mrb, name, &len); mrb_str_cat(mrb, path, str, len); if (RSTRING_PTR(path)[0] != '#') { iv_del(mrb, c->iv, mrb_intern_lit(mrb, "__outer__"), NULL); iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path); mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path); } return path; }
static mrb_value method_to_s(mrb_state *mrb, mrb_value self) { mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner")); mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass")); mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); mrb_value str = mrb_str_new_lit(mrb, "#<"); struct RClass *rklass; mrb_str_cat_cstr(mrb, str, mrb_obj_classname(mrb, self)); mrb_str_cat_lit(mrb, str, ": "); rklass = mrb_class_ptr(klass); if (mrb_class_ptr(owner) == rklass) { mrb_str_cat_str(mrb, str, mrb_funcall(mrb, owner, "to_s", 0)); mrb_str_cat_lit(mrb, str, "#"); mrb_str_cat_str(mrb, str, mrb_funcall(mrb, name, "to_s", 0)); } else { mrb_str_cat_cstr(mrb, str, mrb_class_name(mrb, rklass)); mrb_str_cat_lit(mrb, str, "("); mrb_str_cat_str(mrb, str, mrb_funcall(mrb, owner, "to_s", 0)); mrb_str_cat_lit(mrb, str, ")#"); mrb_str_cat_str(mrb, str, mrb_funcall(mrb, name, "to_s", 0)); } mrb_str_cat_lit(mrb, str, ">"); return str; }
mrb_value cfunc_struct_define_struct(mrb_state *mrb, mrb_value klass) { mrb_value elements_mrb; mrb_get_args(mrb, "A", &elements_mrb); struct RArray *elements = mrb_ary_ptr(elements_mrb); ffi_type *tm_type = mrb_malloc(mrb, sizeof(ffi_type)); tm_type->type = FFI_TYPE_STRUCT; tm_type->size = tm_type->alignment = 0; ffi_type **tm_type_elements = mrb_malloc(mrb, sizeof(ffi_type*) * (elements->len + 1)); int i; for(i = 0; i < elements->len; ++i) { tm_type_elements[i] = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(elements->ptr[i]))->ffi_type_value; } tm_type_elements[i] = NULL; tm_type->elements = tm_type_elements; struct mrb_ffi_type *mft = mrb_malloc(mrb, sizeof(struct mrb_ffi_type)); mft->name = mrb_class_name(mrb, mrb_class_ptr(klass)); mft->ffi_type_value = tm_type; mft->mrb_to_c = &cfunc_type_ffi_struct_mrb_to_c; mft->c_to_mrb = &cfunc_type_ffi_struct_c_to_mrb; mrb_value __ffi_type = mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &cfunc_struct_data_type, mft)); mrb_obj_iv_set(mrb, (struct RObject*)(mrb_class_ptr(klass)), mrb_intern_cstr(mrb, "@ffi_type"), __ffi_type); return mrb_nil_value(); }
/* * code-seq: * struct.eql?(other) -> true or false * * Two structures are equal if they are the same object, or if all their * fields are equal (using <code>eql?</code>). */ static mrb_value mrb_struct_eql(mrb_state *mrb, mrb_value s) { mrb_value s2; mrb_value *ptr, *ptr2; mrb_int i, len; mrb_bool eql_p; mrb_get_args(mrb, "o", &s2); if (mrb_obj_equal(mrb, s, s2)) { eql_p = 1; } else if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct") || mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) { eql_p = 0; } else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) { mrb_bug(mrb, "inconsistent struct"); /* should never happen */ eql_p = 0; /* This substuture is just to suppress warnings. never called. */ } else { ptr = RSTRUCT_PTR(s); ptr2 = RSTRUCT_PTR(s2); len = RSTRUCT_LEN(s); eql_p = 1; for (i=0; i<len; i++) { if (!mrb_eql(mrb, ptr[i], ptr2[i])) { eql_p = 0; break; } } } return mrb_bool_value(eql_p); }
static void print_backtrace_saved(mrb_state *mrb) { int i, ai; FILE *stream = stderr; fprintf(stream, "trace:\n"); ai = mrb_gc_arena_save(mrb); for (i = 0; i < mrb->backtrace.n; i++) { mrb_backtrace_entry *entry; entry = &(mrb->backtrace.entries[i]); fprintf(stream, "\t[%d] %s:%d", i, entry->filename, entry->lineno); if (entry->method_id != 0) { const char *method_name; method_name = mrb_sym2name(mrb, entry->method_id); if (entry->klass) { fprintf(stream, ":in %s%c%s", mrb_class_name(mrb, entry->klass), entry->sep, method_name); } else { fprintf(stream, ":in %s", method_name); } mrb_gc_arena_restore(mrb, ai); } fprintf(stream, "\n"); } }
static mrb_value unbound_method_bind(mrb_state *mrb, mrb_value self) { struct RObject *me; mrb_value owner = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@owner")); mrb_value name = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@name")); mrb_value proc = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "proc")); mrb_value klass = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@klass")); mrb_value recv; mrb_get_args(mrb, "o", &recv); if (mrb_type(owner) != MRB_TT_MODULE && mrb_class_ptr(owner) != mrb_obj_class(mrb, recv) && !mrb_obj_is_kind_of(mrb, recv, mrb_class_ptr(owner))) { if (mrb_type(owner) == MRB_TT_SCLASS) { mrb_raise(mrb, E_TYPE_ERROR, "singleton method called for a different object"); } else { const char *s = mrb_class_name(mrb, mrb_class_ptr(owner)); mrb_raisef(mrb, E_TYPE_ERROR, "bind argument must be an instance of %S", mrb_str_new_static(mrb, s, strlen(s))); } } me = method_object_alloc(mrb, mrb_class_get(mrb, "Method")); mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@owner"), owner); mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@recv"), recv); mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@name"), name); mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "proc"), proc); mrb_obj_iv_set(mrb, me, mrb_intern_lit(mrb, "@klass"), klass); return mrb_obj_value(me); }
mrb_value mrb_class_find_path(mrb_state *mrb, struct RClass *c) { mrb_value outer, path; mrb_sym name; const char *str; mrb_int len; mrb_sym osym = mrb_intern_lit(mrb, "__outer__"); outer = mrb_obj_iv_get(mrb, (struct RObject*)c, osym); if (mrb_nil_p(outer)) return outer; name = find_class_sym(mrb, mrb_class_ptr(outer), c); if (name == 0) return mrb_nil_value(); str = mrb_class_name(mrb, mrb_class_ptr(outer)); path = mrb_str_new_capa(mrb, 40); mrb_str_cat_cstr(mrb, path, str); mrb_str_cat_cstr(mrb, path, "::"); str = mrb_sym2name_len(mrb, name, &len); mrb_str_cat(mrb, path, str, len); iv_del(mrb, c->iv, osym, NULL); iv_put(mrb, c->iv, mrb_intern_lit(mrb, "__classname__"), path); mrb_field_write_barrier_value(mrb, (struct RBasic*)c, path); return path; }
static void output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *data) { int i; if (ciidx >= mrb->c->ciend - mrb->c->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { struct backtrace_location loc; mrb_callinfo *ci; mrb_irep *irep; mrb_code *pc; ci = &mrb->c->cibase[i]; if (!ci->proc) continue; if (MRB_PROC_CFUNC_P(ci->proc)) continue; irep = ci->proc->body.irep; if (mrb->c->cibase[i].err) { pc = mrb->c->cibase[i].err; } else if (i+1 <= ciidx) { pc = mrb->c->cibase[i+1].pc - 1; } else { pc = pc0; } loc.filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); loc.lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); if (loc.lineno == -1) continue; if (ci->target_class == ci->proc->target_class) { loc.sep = "."; } else { loc.sep = "#"; } if (!loc.filename) { loc.filename = "(unknown)"; } loc.method = mrb_sym2name(mrb, ci->mid); loc.class_name = mrb_class_name(mrb, ci->proc->target_class); loc.i = i; func(mrb, &loc, data); } }
mrb_value mrb_struct_members(mrb_state *mrb, mrb_value s) { mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s))); if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) { if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) { mrb_raisef(mrb, E_TYPE_ERROR, "struct size differs (%S required %S given)", mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s))); } } return members; }
struct mrb_ffi_type* rclass_to_mrb_ffi_type(mrb_state *mrb, struct RClass *cls) { struct RClass *cls_ = cls; while(cls) { mrb_value ffi_type = mrb_obj_iv_get(mrb, (struct RObject*)cls, mrb_intern_cstr(mrb, "@ffi_type")); if(mrb_test(ffi_type)) { return (struct mrb_ffi_type*)DATA_PTR(ffi_type); } cls = cls->super; } mrb_raisef(mrb, E_TYPE_ERROR, "%s cannot convert to C value", mrb_class_name(mrb, cls_)); return NULL; }
static mrb_value mrb_mod_to_s(mrb_state *mrb, mrb_value klass) { if (mrb_type(klass) == MRB_TT_SCLASS) { mrb_value s = mrb_str_new(mrb, "#<", 2); mrb_value v = mrb_iv_get(mrb, klass, mrb_intern(mrb, "__attached__")); mrb_str_cat2(mrb, s, "Class:"); switch (mrb_type(v)) { case MRB_TT_CLASS: case MRB_TT_MODULE: case MRB_TT_SCLASS: mrb_str_append(mrb, s, mrb_inspect(mrb, v)); break; default: mrb_str_append(mrb, s, mrb_any_to_s(mrb, v)); break; } mrb_str_cat2(mrb, s, ">"); return s; } else { struct RClass *c = mrb_class_ptr(klass); const char *cn = mrb_class_name(mrb, c); if (!cn) { char buf[256]; int n = 0; switch (mrb_type(klass)) { case MRB_TT_CLASS: n = snprintf(buf, sizeof(buf), "#<Class:%p>", c); break; case MRB_TT_MODULE: n = snprintf(buf, sizeof(buf), "#<Module:%p>", c); break; default: break; } return mrb_str_dup(mrb, mrb_str_new(mrb, buf, n)); } else { return mrb_str_dup(mrb, mrb_str_new_cstr(mrb, cn)); } } }
static void output_backtrace_i(mrb_state *mrb, struct backtrace_location_raw *loc_raw, void *data) { struct backtrace_location loc; struct output_backtrace_args *args = (struct output_backtrace_args *)data; loc.i = loc_raw->i; loc.lineno = loc_raw->lineno; loc.filename = loc_raw->filename; loc.method = mrb_sym2name(mrb, loc_raw->method_id); loc.sep = loc_raw->sep; loc.class_name = mrb_class_name(mrb, loc_raw->klass); args->func(mrb, &loc, args->data); }
static mrb_value inspect_struct(mrb_state *mrb, mrb_value s, int recur) { const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s)); mrb_value members, str = mrb_str_new_lit(mrb, "#<struct "); mrb_value *ptr, *ptr_members; mrb_int i, len; if (cn) { mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, cn)); } if (recur) { return mrb_str_cat_lit(mrb, str, ":...>"); } members = mrb_struct_members(mrb, s); ptr_members = RARRAY_PTR(members); ptr = RSTRUCT_PTR(s); len = RSTRUCT_LEN(s); for (i=0; i<len; i++) { mrb_value slot; mrb_sym id; if (i > 0) { mrb_str_cat_lit(mrb, str, ", "); } else if (cn) { mrb_str_cat_lit(mrb, str, " "); } slot = ptr_members[i]; id = mrb_symbol(slot); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { const char *name; mrb_int len; name = mrb_sym2name_len(mrb, id, &len); mrb_str_append(mrb, str, mrb_str_new(mrb, name, len)); } else { mrb_str_append(mrb, str, mrb_inspect(mrb, slot)); } mrb_str_cat_lit(mrb, str, "="); mrb_str_append(mrb, str, mrb_inspect(mrb, ptr[i])); } mrb_str_cat_lit(mrb, str, ">"); return str; }
mrb_value cfunc_pointer_inspect(mrb_state *mrb, mrb_value self) { struct cfunc_type_data *data = DATA_PTR(self); mrb_value type = mrb_funcall(mrb, mrb_obj_value(mrb_class(mrb, self)), "type", 0); const char* classname = mrb_class_name(mrb, (struct RClass*)mrb_object(type)); if(!classname) { classname = "Unknown pointer"; } char cstr[256]; snprintf(cstr, sizeof(cstr), "<%s pointer=%p>", classname, get_cfunc_pointer_data(data)); return mrb_str_new_cstr(mrb, cstr); }
static void showcallinfo(mrb_state *mrb) { mrb_callinfo *ci; mrb_int ciidx; const char *filename, *method, *sep; int i, line; printf("trace:\n"); ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "ciidx"))); if (ciidx >= mrb->ciend - mrb->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { ci = &mrb->cibase[i]; filename = "(unknown)"; line = -1; if (MRB_PROC_CFUNC_P(ci->proc)) { continue; } else { mrb_irep *irep = ci->proc->body.irep; if (irep->filename != NULL) filename = irep->filename; if (irep->lines != NULL && i+1 <= ciidx) { mrb_code *pc = mrb->cibase[i+1].pc; if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) { line = irep->lines[pc - irep->iseq - 1]; } } } if (ci->target_class == ci->proc->target_class) sep = "."; else sep = "#"; method = mrb_sym2name(mrb, ci->mid); printf("\t[%d] %s:%d%s%s%s%s\n", i, filename, line, method ? ":in " : "", method ? mrb_class_name(mrb, ci->proc->target_class) : "", method ? sep : "", method ? method : ""); } }
mrb_value mrb_mod_cv_get(mrb_state *mrb, struct RClass * c, mrb_sym sym) { struct RClass * cls = c; while (c) { if (c->iv) { iv_tbl *t = c->iv; mrb_value v; if (iv_get(mrb, t, sym, &v)) return v; } c = c->super; } mrb_raisef(mrb, E_NAME_ERROR, "uninitialized class variable %s in %s", mrb_sym2name(mrb, sym), mrb_class_name(mrb, cls)); /* not reached */ return mrb_nil_value(); }
mrb_value mrb_restore_backtrace(mrb_state *mrb) { int i; mrb_value backtrace; backtrace = mrb_ary_new(mrb); for (i = 0; i < mrb->backtrace.n; i++) { int ai; mrb_backtrace_entry *entry; mrb_value mrb_entry; char buf[32]; ai = mrb_gc_arena_save(mrb); entry = &(mrb->backtrace.entries[i]); mrb_entry = mrb_str_new_cstr(mrb, entry->filename); snprintf(buf, sizeof(buf), ":%d", entry->lineno); mrb_str_cat_cstr(mrb, mrb_entry, buf); if (entry->method_id != 0) { mrb_str_cat_lit(mrb, mrb_entry, ":in "); if (entry->klass) { mrb_str_cat_cstr(mrb, mrb_entry, mrb_class_name(mrb, entry->klass)); mrb_str_cat(mrb, mrb_entry, &entry->sep, 1); } mrb_str_cat_cstr(mrb, mrb_entry, mrb_sym2name(mrb, entry->method_id)); } mrb_ary_push(mrb, backtrace, mrb_entry); mrb_gc_arena_restore(mrb, ai); } return backtrace; }
static void mrb_search_method_owner(mrb_state *mrb, struct RClass *c, mrb_value obj, mrb_sym name, struct RClass **owner, struct RProc **proc, mrb_bool unbound) { mrb_value ret; const char *s; *owner = c; *proc = method_search_vm(mrb, owner, name); if (!*proc) { if (unbound) { goto name_error; } if (!mrb_respond_to(mrb, obj, mrb_intern_lit(mrb, "respond_to_missing?"))) { goto name_error; } ret = mrb_funcall(mrb, obj, "respond_to_missing?", 2, mrb_symbol_value(name), mrb_true_value()); if (!mrb_test(ret)) { goto name_error; } *owner = c; } while ((*owner)->tt == MRB_TT_ICLASS) *owner = (*owner)->c; return; name_error: s = mrb_class_name(mrb, c); mrb_raisef( mrb, E_NAME_ERROR, "undefined method `%S' for class `%S'", mrb_sym2str(mrb, name), mrb_str_new_static(mrb, s, strlen(s)) ); }
void mrb_print_backtrace(mrb_state *mrb) { #ifdef ENABLE_STDIO mrb_callinfo *ci; mrb_int ciidx; const char *filename, *method, *sep; int i, line; printf("trace:\n"); ciidx = mrb_fixnum(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "ciidx"))); if (ciidx >= mrb->ciend - mrb->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { ci = &mrb->cibase[i]; filename = "(unknown)"; line = -1; if (MRB_PROC_CFUNC_P(ci->proc)) { continue; } else { mrb_irep *irep = ci->proc->body.irep; if (irep->filename != NULL) filename = irep->filename; if (irep->lines != NULL) { mrb_code *pc; if (i+1 <= ciidx) { pc = mrb->cibase[i+1].pc; } else { pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, mrb->exc, mrb_intern(mrb, "lastpc"))); } if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) { line = irep->lines[pc - irep->iseq - 1]; } } } if (line == -1) continue; if (ci->target_class == ci->proc->target_class) sep = "."; else sep = "#"; method = mrb_sym2name(mrb, ci->mid); if (method) { const char *cn = mrb_class_name(mrb, ci->proc->target_class); if (cn) { printf("\t[%d] %s:%d:in %s%s%s\n", i, filename, line, cn, sep, method); } else { printf("\t[%d] %s:%d:in %s\n", i, filename, line, method); } } else { printf("\t[%d] %s:%d\n", i, filename, line); } } #endif }
static void output_backtrace(mrb_state *mrb, mrb_int ciidx, mrb_code *pc0, output_stream_func func, void *stream) { mrb_callinfo *ci; const char *filename, *method, *sep; int i, lineno, tracehead = 1; if (ciidx >= mrb->c->ciend - mrb->c->cibase) ciidx = 10; /* ciidx is broken... */ for (i = ciidx; i >= 0; i--) { ci = &mrb->c->cibase[i]; filename = NULL; lineno = -1; if (!ci->proc) continue; if (MRB_PROC_CFUNC_P(ci->proc)) { continue; } else { mrb_irep *irep = ci->proc->body.irep; mrb_code *pc; if (mrb->c->cibase[i].err) { pc = mrb->c->cibase[i].err; } else if (i+1 <= ciidx) { pc = mrb->c->cibase[i+1].pc - 1; } else { pc = pc0; } filename = mrb_debug_get_filename(irep, (uint32_t)(pc - irep->iseq)); lineno = mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq)); } if (lineno == -1) continue; if (ci->target_class == ci->proc->target_class) sep = "."; else sep = "#"; if (!filename) { filename = "(unknown)"; } if (tracehead) { func(mrb, stream, 1, "trace:\n"); tracehead = 0; } method = mrb_sym2name(mrb, ci->mid); if (method) { const char *cn = mrb_class_name(mrb, ci->proc->target_class); if (cn) { func(mrb, stream, 1, "\t[%d] ", i); func(mrb, stream, 0, "%s:%d:in %s%s%s", filename, lineno, cn, sep, method); func(mrb, stream, 1, "\n"); } else { func(mrb, stream, 1, "\t[%d] ", i); func(mrb, stream, 0, "%s:%d:in %s", filename, lineno, method); func(mrb, stream, 1, "\n"); } } else { func(mrb, stream, 1, "\t[%d] ", i); func(mrb, stream, 0, "%s:%d", filename, lineno); func(mrb, stream, 1, "\n"); } } }
static mrb_value cfunc_call(mrb_state *mrb, mrb_value self) { int margc; mrb_value mresult_type, mname, *margs; void **values = NULL; ffi_type **args = NULL; mrb_get_args(mrb, "oo*", &mresult_type, &mname, &margs, &margc); void *fp = NULL; if(mrb_string_p(mname) || mrb_symbol_p(mname)) { void *dlh = dlopen(NULL, RTLD_LAZY); fp = dlsym(dlh, mrb_string_value_ptr(mrb, mname)); dlclose(dlh); } else { fp = cfunc_pointer_ptr(mname); } if(fp == NULL) { mrb_raisef(mrb, E_NAME_ERROR, "can't find C function %s", mrb_string_value_ptr(mrb, mname)); goto cfunc_call_exit; } args = malloc(sizeof(ffi_type*) * margc); values = malloc(sizeof(void*) * margc); mrb_sym sym_to_ffi_value = mrb_intern(mrb, "to_ffi_value"); mrb_value nil_ary[1]; nil_ary[0] = mrb_nil_value(); for(int i = 0; i < margc; ++i) { if(mrb_respond_to(mrb, margs[i], sym_to_ffi_value)) { args[i] = mrb_value_to_mrb_ffi_type(mrb, margs[i])->ffi_type_value; values[i] = cfunc_pointer_ptr(mrb_funcall_argv(mrb, margs[i], sym_to_ffi_value, 1, nil_ary)); } else { cfunc_mrb_raise_without_jump(mrb, E_TYPE_ERROR, "ignore argument type %s", mrb_obj_classname(mrb, margs[i])); goto cfunc_call_exit; } } ffi_type *result_type = rclass_to_mrb_ffi_type(mrb, mrb_class_ptr(mresult_type))->ffi_type_value; if (result_type == NULL) { cfunc_mrb_raise_without_jump(mrb, E_ARGUMENT_ERROR, "ignore return type %s", mrb_class_name(mrb, mrb_class_ptr(mresult_type))); goto cfunc_call_exit; } mrb_value mresult = mrb_nil_value(); ffi_cif cif; if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, margc, result_type, args) == FFI_OK) { void *result; if(result_type->size > sizeof(long)) { result = malloc(result_type->size); } else if(result_type->size) { result = malloc(sizeof(long)); } else { result = NULL; } ffi_call(&cif, fp, result, values); if(result) { mrb_value result_ptr = cfunc_pointer_new_with_pointer(mrb, result, true); mresult = mrb_funcall(mrb, mresult_type, "refer", 1, result_ptr); } } else { mrb_raisef(mrb, E_NAME_ERROR, "Can't find C function %s", mname); goto cfunc_call_exit; } cfunc_call_exit: free(values); free(args); return mresult; }
const char* mrb_obj_classname(mrb_state *mrb, mrb_value obj) { return mrb_class_name(mrb, mrb_obj_class(mrb, obj)); }