VALUE rb_block_call(VALUE obj, ID meth, int argc, VALUE* argv, VALUE(*cb)(ANYARGS), VALUE cb_data) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); if(cb) { Proc* prc = capi::wrap_c_function((void*)cb, cb_data, C_BLOCK_CALL); env->set_outgoing_block(env->get_handle(prc)); } else { env->set_outgoing_block(env->get_handle(env->block())); } return rb_funcall2(obj, meth, argc, argv); }
VALUE rb_funcall(VALUE receiver, ID method_name, int arg_count, ...) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); va_list varargs; va_start(varargs, arg_count); Object* args[arg_count]; for(int i = 0; i < arg_count; i++) { args[i] = env->get_object(va_arg(varargs, VALUE)); } va_end(varargs); Object* blk = cNil; if(VALUE blk_handle = env->outgoing_block()) { blk = env->get_object(blk_handle); env->set_outgoing_block(0); } return capi_funcall_backend_native(env, "", 0, env->get_object(receiver), reinterpret_cast<Symbol*>(method_name), arg_count, args, blk); }
/** * Common implementation for rb_funcall* */ VALUE capi_funcall_backend(const char* file, int line, VALUE receiver, ID method_name, size_t arg_count, VALUE* arg_array) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); env->flush_cached_data(); Array* args = Array::create(env->state(), arg_count); for(size_t i = 0; i < arg_count; i++) { args->set(env->state(), i, env->get_object(arg_array[i])); } Object* blk = RBX_Qnil; if(VALUE blk_handle = env->outgoing_block()) { blk = env->get_object(blk_handle); env->set_outgoing_block(0); } Object* recv = env->get_object(receiver); Object* ret = recv->send(env->state(), env->current_call_frame(), reinterpret_cast<Symbol*>(method_name), args, blk); env->update_cached_data(); // An exception occurred if(!ret) env->current_ep()->return_to(env); return env->get_handle(ret); }
VALUE rb_iterate(VALUE(*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); // Minor optimization. if(ifunc == rb_each && kind_of<Array>(env->get_object(ary))) { for(size_t i = 0; i < rb_ary_size(ary); i++) { (*cb)(rb_ary_entry(ary, i), cb_data, Qnil); } return ary; } NativeMethod* nm = NativeMethod::create(env->state(), (String*)Qnil, env->state()->shared.globals.rubinius.get(), env->state()->symbol("call"), (void*)cb, Fixnum::from(ITERATE_BLOCK)); nm->set_ivar(env->state(), env->state()->symbol("cb_data"), env->get_object(cb_data)); Proc* prc = Proc::create(env->state(), env->state()->shared.globals.proc.get()); prc->bound_method(env->state(), nm); env->set_outgoing_block(env->get_handle(prc)); return (*ifunc)(ary); }
/** * Common implementation for rb_funcall* */ VALUE capi_funcall_backend(const char* file, int line, VALUE receiver, ID method_name, size_t arg_count, VALUE* arg_array) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); env->flush_cached_data(); Array* args = Array::create(env->state(), arg_count); for(size_t i = 0; i < arg_count; i++) { args->set(env->state(), i, env->get_object(arg_array[i])); } Object* blk = cNil; if(VALUE blk_handle = env->outgoing_block()) { blk = env->get_object(blk_handle); env->set_outgoing_block(0); } Object* recv = env->get_object(receiver); // Unlock, we're leaving extension code. LEAVE_CAPI(env->state()); Object* ret = recv->send(env->state(), env->current_call_frame(), reinterpret_cast<Symbol*>(method_name), args, blk); // We need to get the handle for the return value before getting // the GEL so that ret isn't accidentally GCd while we wait. VALUE ret_handle = 0; if(ret) ret_handle = env->get_handle(ret); // Re-entering extension code ENTER_CAPI(env->state()); env->update_cached_data(); // An exception occurred if(!ret) env->current_ep()->return_to(env); return ret_handle; }
VALUE rb_iterate(VALUE(*ifunc)(VALUE), VALUE ary, VALUE(*cb)(ANYARGS), VALUE cb_data) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); // Minor optimization. if(ifunc == rb_each && kind_of<Array>(env->get_object(ary))) { for(long i = 0; i < rb_ary_size(ary); i++) { (*cb)(rb_ary_entry(ary, i), cb_data, Qnil); } return ary; } Proc* prc = capi::wrap_c_function((void*)cb, cb_data, ITERATE_BLOCK); env->set_outgoing_block(env->get_handle(prc)); return (*ifunc)(ary); }
VALUE rb_funcall2(VALUE receiver, ID method_name, int arg_count, const VALUE* v_args) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); Object** args = reinterpret_cast<Object**>(alloca(sizeof(Object**) * arg_count)); for(int i = 0; i < arg_count; i++) { args[i] = env->get_object(v_args[i]); } Object* blk = RBX_Qnil; if(VALUE blk_handle = env->outgoing_block()) { blk = env->get_object(blk_handle); env->set_outgoing_block(0); } return capi_funcall_backend_native(env, "", 0, env->get_object(receiver), reinterpret_cast<Symbol*>(method_name), arg_count, args, blk); }