struct mrb_ffi_type* mrb_value_to_mrb_ffi_type(mrb_state *mrb, mrb_value val) { if(mrb_nil_p(val)) { return rclass_to_mrb_ffi_type(mrb, cfunc_state(mrb, NULL)->pointer_class); } switch(mrb_type(val)) { case MRB_TT_TRUE: case MRB_TT_FALSE: return rclass_to_mrb_ffi_type(mrb, cfunc_state(mrb, NULL)->sint32_class); default: return rclass_to_mrb_ffi_type(mrb, mrb_object(val)->c); } }
mrb_value cfunc_rubyvm_class_thread(mrb_state *mrb, mrb_value klass) { // init bindle data with RubyVM object struct RClass *c = mrb_class_ptr(klass); struct cfunc_rubyvm_data *data = malloc(sizeof(struct cfunc_rubyvm_data)); data->mrb_state_init = cfunc_state(mrb)->mrb_state_init; mrb_value self = mrb_obj_value((struct RObject *)Data_Wrap_Struct(mrb, c, &cfunc_rubyvm_data_type, data)); // load script mrb_value filename, str; mrb_get_args(mrb, "S", &filename); str = mrb_str_new_cstr(mrb, "mruby_data_"); mrb_str_concat(mrb, str, mrb_str_new(mrb, RSTRING_PTR(filename), RSTRING_LEN(filename))); void *dlh = dlopen(NULL, RTLD_LAZY); data->mrb_data = (const char *)dlsym(dlh, RSTRING_PTR(str)); if (!data->mrb_data) { dlclose(dlh); mrb_raisef(mrb, E_SCRIPT_ERROR, "file '%s' not found.", RSTRING_PTR(str)); } // initial pthread data->queue = create_vector(); pthread_mutex_init(&data->queue_mutex, NULL); pthread_cond_init(&data->queue_cond, NULL); pthread_create(&data->thread, NULL, cfunc_rubyvm_open, (void*)data); return self; }
mrb_value cfunc_rubyvm_dispatch(mrb_state *mrb, mrb_value self) { struct cfunc_rubyvm_data *data = mrb_get_datatype(mrb, self, &cfunc_rubyvm_data_type); mrb_value name_obj, *args; int args_len; mrb_get_args(mrb, "o*", &name_obj, &args, &args_len); struct queue_task *task = malloc(sizeof(struct queue_task)); task->refcount = 2; task->result = NULL; task->status = queue_task_queued; pthread_mutex_init(&task->sync_mutex, NULL); pthread_cond_init(&task->sync_cond, NULL); const char* name = mrb_string_value_ptr(mrb, name_obj); int name_len = strlen(name); task->name = malloc(name_len+1); strncpy(task->name, name, name_len+1); task->args_len = args_len; task->args = malloc(sizeof(struct task_arg) * task->args_len); for(int i=0; i<args_len; ++i) { task->args[i] = mrb_value_to_task_arg(mrb, args[i]); } pthread_mutex_lock(&data->queue_mutex); vector_enqueue(data->queue, task); pthread_cond_signal(&data->queue_cond); pthread_mutex_unlock(&data->queue_mutex); return mrb_obj_value((struct RObject *)Data_Wrap_Struct(mrb, cfunc_state(mrb)->rubyvm_task_class, &cfunc_rubyvm_task_data_type, task)); }
void init_cfunc_pointer(mrb_state *mrb, struct RClass* module) { struct cfunc_state *state = cfunc_state(mrb, module); struct RClass *pointer_class = mrb_define_class_under(mrb, module, "Pointer", state->type_class); mrb_value ffi_type = mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &cfunc_pointer_ffi_data_type, &pointer_mrb_ffi_type)); mrb_obj_iv_set(mrb, (struct RObject*)pointer_class, mrb_intern_cstr(mrb, "@ffi_type"), ffi_type); state->pointer_class = pointer_class; mrb_define_class_method(mrb, pointer_class, "refer", cfunc_pointer_refer, ARGS_REQ(1)); mrb_define_class_method(mrb, pointer_class, "malloc", cfunc_pointer_class_malloc, ARGS_REQ(1)); mrb_define_method(mrb, pointer_class, "initialize", cfunc_pointer_initialize, ARGS_ANY()); mrb_define_method(mrb, pointer_class, "realloc", cfunc_pointer_realloc, ARGS_REQ(1)); mrb_define_method(mrb, pointer_class, "free", cfunc_pointer_free, ARGS_NONE()); mrb_define_method(mrb, pointer_class, "inspect", cfunc_pointer_inspect, ARGS_NONE()); mrb_define_method(mrb, pointer_class, "is_null?", cfunc_pointer_is_null, ARGS_NONE()); mrb_define_method(mrb, pointer_class, "autofree", cfunc_pointer_autofree, ARGS_NONE()); mrb_define_method(mrb, pointer_class, "offset", cfunc_pointer_offset, ARGS_REQ(1)); mrb_define_method(mrb, pointer_class, "to_s", cfunc_pointer_to_s, ARGS_NONE()); // add method to system classes mrb_define_method(mrb, mrb->string_class, "addr", cfunc_string_addr, ARGS_NONE()); mrb_obj_iv_set(mrb, (struct RObject *)mrb->string_class, mrb_intern_cstr(mrb, "@ffi_type"), ffi_type); }
void init_cfunc_struct(mrb_state *mrb, struct RClass* module) { struct cfunc_state *state = cfunc_state(mrb, module); struct RClass *struct_class = mrb_define_class_under(mrb, module, "Struct", mrb->object_class); set_cfunc_state(mrb, struct_class, state); state->struct_class = struct_class; mrb_define_class_method(mrb, struct_class, "define_struct", cfunc_struct_define_struct, ARGS_REQ(1)); }
void init_cfunc_closure(mrb_state *mrb, struct RClass* module) { struct cfunc_state *state = cfunc_state(mrb, module); struct RClass *closure_class = mrb_define_class_under(mrb, module, "Closure", state->pointer_class); state->closure_class = closure_class; mrb_value ffi_type = mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &cfunc_closure_ffi_type_data_type, &closure_mrb_ffi_type)); mrb_obj_iv_set(mrb, (struct RObject*)closure_class, mrb_intern_cstr(mrb, "@ffi_type"), ffi_type); mrb_define_method(mrb, closure_class, "initialize", cfunc_closure_initialize, ARGS_ANY()); }
mrb_value cfunc_pointer_new_with_pointer(mrb_state *mrb, void *p, bool autofree) { struct cfunc_type_data *data = mrb_malloc(mrb, sizeof(struct cfunc_type_data)); data->refer = false; data->autofree = autofree; set_cfunc_pointer_data(data, p); struct cfunc_state *state = cfunc_state(mrb, NULL); return mrb_obj_value(Data_Wrap_Struct(mrb, state->pointer_class, &cfunc_pointer_data_type, data)); }
void init_cfunc_rubyvm(mrb_state *mrb, struct RClass* module, void (*mrb_state_init)(mrb_state*)) { cfunc_state(mrb)->mrb_state_init = mrb_state_init; struct RClass *rubyvm_class = mrb_define_class_under(mrb, module, "RubyVM", mrb->object_class); cfunc_state(mrb)->rubyvm_class = rubyvm_class; mrb_define_class_method(mrb, rubyvm_class, "thread", cfunc_rubyvm_class_thread, ARGS_REQ(1)); mrb_define_method(mrb, rubyvm_class, "dispatch", cfunc_rubyvm_dispatch, ARGS_ANY()); struct RClass *rubyvm_task_class = mrb_define_class_under(mrb, cfunc_state(mrb)->rubyvm_class, "Task", mrb->object_class); cfunc_state(mrb)->rubyvm_task_class = rubyvm_task_class; mrb_define_method(mrb, rubyvm_task_class, "wait", cfunc_rubyvm_task_wait, ARGS_NONE()); mrb_define_method(mrb, rubyvm_task_class, "result", cfunc_rubyvm_task_result, ARGS_NONE()); mrb_define_method(mrb, rubyvm_task_class, "status", cfunc_rubyvm_task_status, ARGS_NONE()); mrb_define_const(mrb, rubyvm_task_class, "QUEUED", mrb_fixnum_value(queue_task_queued)); mrb_define_const(mrb, rubyvm_task_class, "RUNNING", mrb_fixnum_value(queue_task_running)); mrb_define_const(mrb, rubyvm_task_class, "FINISHED", mrb_fixnum_value(queue_task_finished)); }
void init_cfunc_type(mrb_state *mrb, struct RClass* module) { struct cfunc_state *state = cfunc_state(mrb, module); struct RClass *type_class = mrb_define_class_under(mrb, module, "Type", mrb->object_class); MRB_SET_INSTANCE_TT(type_class, MRB_TT_DATA); state->type_class = type_class; set_cfunc_state(mrb, type_class, state); int ai = mrb_gc_arena_save(mrb); mrb_define_class_method(mrb, type_class, "refer", cfunc_type_class_refer, ARGS_REQ(1)); mrb_define_class_method(mrb, type_class, "size", cfunc_type_size, ARGS_NONE()); mrb_define_class_method(mrb, type_class, "align", cfunc_type_align, ARGS_NONE()); mrb_define_class_method(mrb, type_class, "get", cfunc_type_class_get, ARGS_REQ(1)); mrb_define_class_method(mrb, type_class, "set", cfunc_type_class_set, ARGS_REQ(2)); mrb_define_method(mrb, type_class, "initialize", cfunc_type_initialize, ARGS_ANY()); mrb_define_method(mrb, type_class, "value", cfunc_type_get_value, ARGS_NONE()); mrb_define_method(mrb, type_class, "value=", cfunc_type_set_value, ARGS_REQ(1)); mrb_define_method(mrb, type_class, "addr", cfunc_type_addr, ARGS_NONE()); mrb_define_method(mrb, type_class, "to_ffi_value", cfunc_type_addr, ARGS_NONE()); DONE; int map_size = sizeof(types) / sizeof(struct mrb_ffi_type); int i; for(i = 0; i < map_size; ++i) { struct RClass *new_class = mrb_define_class_under(mrb, module, types[i].name, type_class); mrb_value ffi_type = mrb_obj_value(Data_Wrap_Struct(mrb, mrb->object_class, &cfunc_class_ffi_data_type, &types[i])); mrb_obj_iv_set(mrb, (struct RObject*)new_class, mrb_intern_cstr(mrb, "@ffi_type"), ffi_type); } DONE; mrb_value mod = mrb_obj_value(module); state->void_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "Void"))); state->uint8_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "UInt8"))); state->sint8_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "SInt8"))); state->uint16_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "UInt16"))); state->sint16_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "SInt16"))); state->uint32_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "UInt32"))); state->sint32_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "SInt32"))); state->uint64_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "UInt64"))); state->sint64_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "SInt64"))); state->float_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "Float"))); state->double_class = mrb_class_ptr(mrb_const_get(mrb, mod, mrb_intern_cstr(mrb, "Double"))); DONE; mrb_define_class_method(mrb, mrb->nil_class, "size", cfunc_nil_size, ARGS_NONE()); mrb_define_class_method(mrb, mrb->nil_class, "align", cfunc_nil_align, ARGS_NONE()); DONE; // uint64 specific struct RClass *uint64_class = state->uint64_class; mrb_define_class_method(mrb, uint64_class, "get", cfunc_uint64_class_get, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "value", cfunc_uint64_get_value, ARGS_NONE()); mrb_define_method(mrb, uint64_class, "low", cfunc_uint64_get_low, ARGS_NONE()); mrb_define_method(mrb, uint64_class, "low=", cfunc_uint64_set_low, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "high", cfunc_uint64_get_high, ARGS_NONE()); mrb_define_method(mrb, uint64_class, "high=", cfunc_uint64_set_high, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "to_s", cfunc_uint64_to_s, ARGS_REQ(1)); mrb_define_method(mrb, uint64_class, "divide", cfunc_uint64_divide, ARGS_REQ(1)); DONE; // sint64 specific struct RClass *sint64_class = state->sint64_class; mrb_define_class_method(mrb, sint64_class, "get", cfunc_sint64_class_get, ARGS_REQ(1)); mrb_define_method(mrb, sint64_class, "value", cfunc_sint64_get_value, ARGS_NONE()); mrb_define_method(mrb, sint64_class, "low", cfunc_uint64_get_low, ARGS_NONE()); mrb_define_method(mrb, sint64_class, "low=", cfunc_uint64_set_low, ARGS_REQ(1)); mrb_define_method(mrb, sint64_class, "high", cfunc_uint64_get_high, ARGS_NONE()); mrb_define_method(mrb, sint64_class, "high=", cfunc_uint64_set_high, ARGS_REQ(1)); mrb_define_method(mrb, sint64_class, "to_s", cfunc_int64_to_s, ARGS_REQ(1)); DONE; }