Ejemplo n.º 1
0
Archivo: struct.c Proyecto: nyanp/mruby
/*
 *  call-seq:
 *     Struct.new( [aString] [, aSym]+> )    -> StructClass
 *     StructClass.new(arg, ...)             -> obj
 *     StructClass[arg, ...]                 -> obj
 *
 *  Creates a new class, named by <i>aString</i>, containing accessor
 *  methods for the given symbols. If the name <i>aString</i> is
 *  omitted, an anonymous structure class will be created. Otherwise,
 *  the name of this struct will appear as a constant in class
 *  <code>Struct</code>, so it must be unique for all
 *  <code>Struct</code>s in the system and should start with a capital
 *  letter. Assigning a structure class to a constant effectively gives
 *  the class the name of the constant.
 *
 *  <code>Struct::new</code> returns a new <code>Class</code> object,
 *  which can then be used to create specific instances of the new
 *  structure. The number of actual parameters must be
 *  less than or equal to the number of attributes defined for this
 *  class; unset parameters default to <code>nil</code>.  Passing too many
 *  parameters will raise an <code>ArgumentError</code>.
 *
 *  The remaining methods listed in this section (class and instance)
 *  are defined for this generated class.
 *
 *     # Create a structure with a name in Struct
 *     Struct.new("Customer", :name, :address)    #=> Struct::Customer
 *     Struct::Customer.new("Dave", "123 Main")   #=> #<struct Struct::Customer name="Dave", address="123 Main">
 *
 *     # Create a structure named by its constant
 *     Customer = Struct.new(:name, :address)     #=> Customer
 *     Customer.new("Dave", "123 Main")           #=> #<struct Customer name="Dave", address="123 Main">
 */
static mrb_value
mrb_struct_s_def(mrb_state *mrb, mrb_value klass)
{
  mrb_value name, rest;
  mrb_value *pargv;
  int argcnt;
  mrb_int i;
  mrb_value b, st;
  mrb_sym id;
  mrb_value *argv;
  int argc;

  name = mrb_nil_value();
  rest = mrb_nil_value();
  mrb_get_args(mrb, "*&", &argv, &argc, &b);
  if (argc == 0) { /* special case to avoid crash */
    rest = mrb_ary_new(mrb);
  }
  else {
    if (argc > 0) name = argv[0];
    if (argc > 1) rest = argv[1];
    if (mrb_array_p(rest)) {
      if (!mrb_nil_p(name) && mrb_symbol_p(name)) {
        /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
        mrb_ary_unshift(mrb, rest, name);
        name = mrb_nil_value();
      }
    }
    else {
      pargv = &argv[1];
      argcnt = argc-1;
      if (!mrb_nil_p(name) && mrb_symbol_p(name)) {
        /* 1stArgument:symbol -> name=nil rest=argv[0]-[n] */
        name = mrb_nil_value();
        pargv = &argv[0];
        argcnt++;
      }
      rest = mrb_ary_new_from_values(mrb, argcnt, pargv);
    }
    for (i=0; i<RARRAY_LEN(rest); i++) {
      id = mrb_obj_to_sym(mrb, RARRAY_PTR(rest)[i]);
      RARRAY_PTR(rest)[i] = mrb_symbol_value(id);
    }
  }
  st = make_struct(mrb, name, rest, struct_class(mrb));
  if (!mrb_nil_p(b)) {
    mrb_yield_with_class(mrb, b, 1, &st, st, mrb_class_ptr(klass));
  }

  return st;
}
Ejemplo n.º 2
0
Archivo: struct.c Proyecto: nyanp/mruby
/*
 *  call-seq:
 *     struct[symbol]    -> anObject
 *     struct[fixnum]    -> anObject
 *
 *  Attribute Reference---Returns the value of the instance variable
 *  named by <i>symbol</i>, or indexed (0..length-1) by
 *  <i>fixnum</i>. Will raise <code>NameError</code> if the named
 *  variable does not exist, or <code>IndexError</code> if the index is
 *  out of range.
 *
 *     Customer = Struct.new(:name, :address, :zip)
 *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
 *
 *     joe["name"]   #=> "Joe Smith"
 *     joe[:name]    #=> "Joe Smith"
 *     joe[0]        #=> "Joe Smith"
 */
mrb_value
mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx)
{
  mrb_int i;

  if (mrb_string_p(idx)) {
    mrb_value sym = mrb_check_intern_str(mrb, idx);

    if (mrb_nil_p(sym)) {
      mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", idx);
    }
    idx = sym;
  }
  if (mrb_symbol_p(idx)) {
    return mrb_struct_aref_id(mrb, s, mrb_symbol(idx));
  }

  i = mrb_fixnum(idx);
  if (i < 0) i = RSTRUCT_LEN(s) + i;
  if (i < 0)
      mrb_raisef(mrb, E_INDEX_ERROR,
                 "offset %S too small for struct(size:%S)",
                 mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
  if (RSTRUCT_LEN(s) <= i)
    mrb_raisef(mrb, E_INDEX_ERROR,
               "offset %S too large for struct(size:%S)",
               mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
  return RSTRUCT_PTR(s)[i];
}
Ejemplo n.º 3
0
/*
 *  call-seq:
 *     obj.method_missing(symbol [, *args] )   -> result
 *
 *  Invoked by Ruby when <i>obj</i> is sent a message it cannot handle.
 *  <i>symbol</i> is the symbol for the method called, and <i>args</i>
 *  are any arguments that were passed to it. By default, the interpreter
 *  raises an error when this method is called. However, it is possible
 *  to override the method to provide more dynamic behavior.
 *  If it is decided that a particular method should not be handled, then
 *  <i>super</i> should be called, so that ancestors can pick up the
 *  missing method.
 *  The example below creates
 *  a class <code>Roman</code>, which responds to methods with names
 *  consisting of roman numerals, returning the corresponding integer
 *  values.
 *
 *     class Roman
 *       def romanToInt(str)
 *         # ...
 *       end
 *       def method_missing(methId)
 *         str = methId.id2name
 *         romanToInt(str)
 *       end
 *     end
 *
 *     r = Roman.new
 *     r.iv      #=> 4
 *     r.xxiii   #=> 23
 *     r.mm      #=> 2000
 */
static mrb_value
mrb_bob_missing(mrb_state *mrb, mrb_value mod)
{
  mrb_value name, *a;
  int alen;
  mrb_value inspect;

  mrb_get_args(mrb, "o*", &name, &a, &alen);
  if (!mrb_symbol_p(name)) {
    mrb_raise(mrb, E_TYPE_ERROR, "name should be a symbol");
  }

  if (mrb_respond_to(mrb,mod,mrb_intern2(mrb,"inspect",7))){
    inspect = mrb_funcall(mrb, mod, "inspect", 0);
    if (RSTRING_LEN(inspect) > 64) {
      inspect = mrb_any_to_s(mrb, mod);
    }
  }
  else {
    inspect = mrb_any_to_s(mrb, mod);
  }

  mrb_raisef(mrb, E_NOMETHOD_ERROR, "undefined method '%S' for %S",
             mrb_sym2str(mrb, mrb_symbol(name)), inspect);
  /* not reached */
  return mrb_nil_value();
}
Ejemplo n.º 4
0
Archivo: struct.c Proyecto: nyanp/mruby
mrb_value
mrb_struct_aset(mrb_state *mrb, mrb_value s)
{
  mrb_int i;
  mrb_value idx;
  mrb_value val;

  mrb_get_args(mrb, "oo", &idx, &val);

  if (mrb_string_p(idx) || mrb_symbol_p(idx)) {
    return mrb_struct_aset_id(mrb, s, mrb_obj_to_sym(mrb, idx), val);
  }

  i = mrb_fixnum(idx);
  if (i < 0) i = RSTRUCT_LEN(s) + i;
  if (i < 0) {
    mrb_raisef(mrb, E_INDEX_ERROR,
               "offset %S too small for struct(size:%S)",
               mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
  }
  if (RSTRUCT_LEN(s) <= i) {
    mrb_raisef(mrb, E_INDEX_ERROR,
               "offset %S too large for struct(size:%S)",
               mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
  }
  return RSTRUCT_PTR(s)[i] = val;
}
Ejemplo n.º 5
0
static mrb_int getButtonArg(mrb_state *mrb)
{
	mrb_int num;
	mrb_value arg;

	mrb_get_args(mrb, "o", &arg);

	if (mrb_fixnum_p(arg))
	{
		num = mrb_fixnum(arg);
	}
	else if (mrb_symbol_p(arg) && rgssVer >= 3)
	{
		mrb_value symHash = getMrbData(mrb)->buttoncodeHash;
		mrb_value numVal = mrb_hash_fetch(mrb, symHash, arg,
										  mrb_fixnum_value(Input::None));
		num = mrb_fixnum(numVal);
	}
	else
	{
		// FIXME: RMXP allows only few more types that
		// don't make sense (symbols in pre 3, floats)
		num = 0;
	}

	return num;
}
bool rubyval_to_ccvaluemapintkey(mrb_state* mrb, mrb_value arg, cocos2d::ValueMapIntKey* ret, const char* funcName)
{
    if (! mrb_hash_p(arg)) {
        return false;
    }
    
    mrb_value key_arr = mrb_hash_keys(mrb, arg);
    mrb_int len = mrb_ary_len(mrb, key_arr);
    ValueMapIntKey& dict = *ret;
    for (mrb_int i = 0; i < len; i++) {
        mrb_value hk = mrb_ary_ref(mrb, key_arr, i);
        mrb_value hv = mrb_hash_get(mrb, arg, hk);
        int int_key = 0;
        
        if (mrb_string_p(hk)) {
            char *kstr = mrb_str_to_cstr(mrb, hk);
            int_key = atoi(kstr);
        } else if (mrb_symbol_p(hk)) {
            mrb_sym sym = mrb_symbol(hk);
            const char* kstr = mrb_sym2name(mrb, sym);
            int_key = atoi(kstr);
        } else {
            return false;
        }
        Value val;
        if (! rubyval_to_ccvalue(mrb, hv, &val)) {
            return false;
        }
        
        dict[int_key] = val;
    }
    return true;
}
bool rubyval_to_dictionary(mrb_state* mrb, mrb_value arg, __Dictionary** outValue, const char* funcName)
{
    if (! mrb_hash_p(arg)) {
        return false;
    }
    
    mrb_value key_arr = mrb_hash_keys(mrb, arg);
    mrb_int len = mrb_ary_len(mrb, key_arr);
    __Dictionary* dic = __Dictionary::create();
    for (mrb_int i = 0; i < len; i++) {
        mrb_value hk = mrb_ary_ref(mrb, key_arr, i);
        mrb_value hv = mrb_hash_get(mrb, arg, hk);
        if (mrb_string_p(hk)) {
            char *kstr = mrb_str_to_cstr(mrb, hk);
            Ref* ref = to_ref_value(mrb, hv);
            dic->setObject(ref, std::string(kstr));
        } else if (mrb_symbol_p(hk)) {
            mrb_sym sym = mrb_symbol(hk);
            const char* kstr = mrb_sym2name(mrb, sym);
            Ref* ref = to_ref_value(mrb, hv);
            dic->setObject(ref, std::string(kstr));
        } else {
            CCASSERT(false, "not supported key value type");
        }
    }
    *outValue = dic;
    
    return true;
}
Ejemplo n.º 8
0
mrb_value
mrb_struct_aset(mrb_state *mrb, mrb_value s)
{
  long i;
  mrb_value idx;
  mrb_value val;

  mrb_get_args(mrb, "oo", &idx, &val);

  if (mrb_string_p(idx) || mrb_symbol_p(idx)) {
    return mrb_struct_aset_id(mrb, s, mrb_to_id(mrb, idx), val);
  }

  i = mrb_fixnum(idx);
  if (i < 0) i = RSTRUCT_LEN(s) + i;
  if (i < 0) {
    mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)",
	      i, RSTRUCT_LEN(s));
  }
  if (RSTRUCT_LEN(s) <= i) {
    mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)",
	      i, RSTRUCT_LEN(s));
  }
  mrb_struct_modify(s);
  return RSTRUCT_PTR(s)[i] = val;
}
Ejemplo n.º 9
0
static mrb_value
mrb_struct_aset(mrb_state *mrb, mrb_value s)
{
  mrb_int i;
  mrb_value idx;
  mrb_value val;

  mrb_get_args(mrb, "oo", &idx, &val);

  if (mrb_string_p(idx)) {
    mrb_value sym = mrb_check_intern_str(mrb, idx);

    if (mrb_nil_p(sym)) {
      mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
    }
    idx = sym;
  }
  if (mrb_symbol_p(idx)) {
    return mrb_struct_aset_sym(mrb, s, mrb_symbol(idx), val);
  }

  i = mrb_int(mrb, idx);
  if (i < 0) i = RSTRUCT_LEN(s) + i;
  if (i < 0) {
    mrb_raisef(mrb, E_INDEX_ERROR,
               "offset %S too small for struct(size:%S)",
               mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
  }
  if (RSTRUCT_LEN(s) <= i) {
    mrb_raisef(mrb, E_INDEX_ERROR,
               "offset %S too large for struct(size:%S)",
               mrb_fixnum_value(i), mrb_fixnum_value(RSTRUCT_LEN(s)));
  }
  return RSTRUCT_PTR(s)[i] = val;
}
Ejemplo n.º 10
0
static mrb_sym
mrb_sym_value(mrb_state *mrb, mrb_value val)
{
  if (mrb_string_p(val)) {
    return mrb_intern_str(mrb, val);
  }
  else if(!mrb_symbol_p(val)) {
    mrb_value obj = mrb_funcall(mrb, val, "inspect", 0);
    mrb_raisef(mrb, E_TYPE_ERROR, "%s is not a symbol",
         mrb_string_value_ptr(mrb, obj));
  }
  return mrb_symbol(val);
}
Ejemplo n.º 11
0
static mrb_value
get_sym_or_str_arg(mrb_state *mrb)
{
  mrb_value sym_or_str;

  mrb_get_args(mrb, "o", &sym_or_str);

  if (mrb_symbol_p(sym_or_str) || mrb_string_p(sym_or_str)) {
    return sym_or_str;
  } else {
    mrb_value obj = mrb_funcall(mrb, sym_or_str, "inspect", 0);
    mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", obj);
    return mrb_nil_value();
  }
}
Ejemplo n.º 12
0
TMO
mrb_timeout_value(mrb_state *mrb, mrb_value tmo)
{
  if (mrb_fixnum_p(tmo)) {
    return (TMO)mrb_fixnum(tmo);
  }
  if (mrb_symbol_p(tmo)) {
    if (mrb_symbol(tmo) == mrb_intern_lit(mrb, "polling")) {
      return (TMO)TMO_POL;
    }
    if (mrb_symbol(tmo) == mrb_intern_lit(mrb, "forever")) {
      return (TMO)TMO_FEVR;
    }
  }
  mrb_raisef(mrb, E_TYPE_ERROR, "wrong timeout value (%S)", tmo);
}
Ejemplo n.º 13
0
/*
 *  call-seq:
 *     obj.respond_to?(symbol, include_private=false) -> true or false
 *
 *  Returns +true+ if _obj_ responds to the given
 *  method. Private methods are included in the search only if the
 *  optional second parameter evaluates to +true+.
 *
 *  If the method is not implemented,
 *  as Process.fork on Windows, File.lchmod on GNU/Linux, etc.,
 *  false is returned.
 *
 *  If the method is not defined, <code>respond_to_missing?</code>
 *  method is called and the result is returned.
 */
mrb_value
obj_respond_to(mrb_state *mrb, mrb_value self)
{
  mrb_value *argv;
  int argc;
  mrb_value mid, priv;
  mrb_sym id, rtm_id;
  mrb_bool respond_to_p = TRUE;

  mrb_get_args(mrb, "*", &argv, &argc);
  mid = argv[0];
  if (argc > 1) priv = argv[1];
  else priv = mrb_nil_value();

  if (mrb_symbol_p(mid)) {
    id = mrb_symbol(mid);
  }
  else {
    mrb_value tmp;
    if (!mrb_string_p(mid)) {
      tmp = mrb_check_string_type(mrb, mid);
      if (mrb_nil_p(tmp)) {
        tmp = mrb_inspect(mrb, mid);
        mrb_raisef(mrb, E_TYPE_ERROR, "%S is not a symbol", tmp);
      }
    }
    tmp = mrb_check_intern_str(mrb, mid);
    if (mrb_nil_p(tmp)) {
      respond_to_p = FALSE;
    }
    else {
      id = mrb_symbol(tmp);
    }
  }

  if (respond_to_p) {
    respond_to_p = basic_obj_respond_to(mrb, self, id, !mrb_test(priv));
  }

  if (!respond_to_p) {
    rtm_id = mrb_intern2(mrb, "respond_to_missing?", 19);
    if (basic_obj_respond_to(mrb, self, rtm_id, !mrb_test(priv))) {
      return mrb_funcall_argv(mrb, self, rtm_id, argc, argv);
    }
  }
  return mrb_bool_value(respond_to_p);
}
Ejemplo n.º 14
0
static mrb_sym
get_valid_iv_sym(mrb_state *mrb, mrb_value iv_name)
{
  mrb_sym iv_name_id;

  mrb_assert(mrb_symbol_p(iv_name) || mrb_string_p(iv_name));

  if (mrb_string_p(iv_name)) {
    iv_name_id = mrb_intern_cstr(mrb, RSTRING_PTR(iv_name));
    valid_iv_name(mrb, iv_name_id, RSTRING_PTR(iv_name), RSTRING_LEN(iv_name));
  }
  else {
    iv_name_id = mrb_symbol(iv_name);
    check_iv_name(mrb, iv_name_id);
  }

  return iv_name_id;
}
Ejemplo n.º 15
0
/*
 *  call-seq:
 *     struct[symbol]    -> anObject
 *     struct[fixnum]    -> anObject
 *
 *  Attribute Reference---Returns the value of the instance variable
 *  named by <i>symbol</i>, or indexed (0..length-1) by
 *  <i>fixnum</i>. Will raise <code>NameError</code> if the named
 *  variable does not exist, or <code>IndexError</code> if the index is
 *  out of range.
 *
 *     Customer = Struct.new(:name, :address, :zip)
 *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
 *
 *     joe["name"]   #=> "Joe Smith"
 *     joe[:name]    #=> "Joe Smith"
 *     joe[0]        #=> "Joe Smith"
 */
mrb_value
mrb_struct_aref_n(mrb_state *mrb, mrb_value s, mrb_value idx)
{
  long i;

  if (mrb_string_p(idx) || mrb_symbol_p(idx)) {
    return mrb_struct_aref_id(mrb, s, mrb_to_id(mrb, idx));
  }

  i = mrb_fixnum(idx);
  if (i < 0) i = RSTRUCT_LEN(s) + i;
  if (i < 0)
      mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too small for struct(size:%ld)",
           i, RSTRUCT_LEN(s));
  if (RSTRUCT_LEN(s) <= i)
      mrb_raisef(mrb, E_INDEX_ERROR, "offset %ld too large for struct(size:%ld)",
           i, RSTRUCT_LEN(s));
  return RSTRUCT_PTR(s)[i];
}
Ejemplo n.º 16
0
/*
 *  call-seq:
 *     struct[symbol]    -> anObject
 *     struct[fixnum]    -> anObject
 *
 *  Attribute Reference---Returns the value of the instance variable
 *  named by <i>symbol</i>, or indexed (0..length-1) by
 *  <i>fixnum</i>. Will raise <code>NameError</code> if the named
 *  variable does not exist, or <code>IndexError</code> if the index is
 *  out of range.
 *
 *     Customer = Struct.new(:name, :address, :zip)
 *     joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
 *
 *     joe["name"]   #=> "Joe Smith"
 *     joe[:name]    #=> "Joe Smith"
 *     joe[0]        #=> "Joe Smith"
 */
static mrb_value
mrb_struct_aref(mrb_state *mrb, mrb_value s)
{
  mrb_value idx;

  mrb_get_args(mrb, "o", &idx);
  if (mrb_string_p(idx)) {
    mrb_value sym = mrb_check_intern_str(mrb, idx);

    if (mrb_nil_p(sym)) {
      mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
    }
    idx = sym;
  }
  if (mrb_symbol_p(idx)) {
    return struct_aref_sym(mrb, s, mrb_symbol(idx));
  }
  return struct_aref_int(mrb, s, mrb_int(mrb, idx));
}
Ejemplo n.º 17
0
static mrb_value
mrb_mod_method_defined(mrb_state *mrb, mrb_value mod)
{
  mrb_value id;
  mrb_bool method_defined_p;

  id = get_sym_or_str_arg(mrb);
  if (mrb_symbol_p(id)) {
    method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(id));
  } else {
    mrb_value sym = mrb_check_intern_str(mrb, id);
    if (mrb_nil_p(sym)) {
      method_defined_p = FALSE;
    }
    else {
      method_defined_p = mrb_obj_respond_to(mrb_class_ptr(mod), mrb_symbol(sym));
    }
  }
  return mrb_bool_value(method_defined_p);
}
Ejemplo n.º 18
0
static mrb_value
struct_aref_sym(mrb_state *mrb, mrb_value obj, mrb_sym id)
{
  mrb_value members, *ptr;
  const mrb_value *ptr_members;
  mrb_int i, len;

  members = struct_members(mrb, obj);
  ptr_members = RARRAY_PTR(members);
  len = RARRAY_LEN(members);
  ptr = RSTRUCT_PTR(obj);
  for (i=0; i<len; i++) {
    mrb_value slot = ptr_members[i];
    if (mrb_symbol_p(slot) && mrb_symbol(slot) == id) {
      return ptr[i];
    }
  }
  mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
  return mrb_nil_value();       /* not reached */
}
Ejemplo n.º 19
0
static mrb_value
mrb_mod_cvar_defined(mrb_state *mrb, mrb_value mod)
{
  mrb_value id;
  mrb_bool defined_p;

  id = get_sym_or_str_arg(mrb);
  if (mrb_symbol_p(id)) {
    check_cv_name_sym(mrb, mrb_symbol(id));
    defined_p = mrb_cv_defined(mrb, mod, mrb_symbol(id));
  } else {
    mrb_value sym;
    check_cv_name_str(mrb, id);
    sym = mrb_check_intern_str(mrb, id);
    if (mrb_nil_p(sym)) {
      defined_p = FALSE;
    }
    else {
      defined_p = mrb_cv_defined(mrb, mod, mrb_symbol(sym));
    }
  }
  return mrb_bool_value(defined_p);
}
Ejemplo n.º 20
0
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;
}