static mrb_value mrb_env_setenv(mrb_state *mrb, mrb_value name, mrb_value value) { if (mrb_type(name) != MRB_TT_STRING) { mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %s into String", mrb_obj_classname(mrb, name)); return mrb_nil_value(); } if (mrb_nil_p(value)) { return mrb_env_unsetenv(mrb, name); } if (mrb_type(value) != MRB_TT_STRING) { mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %s into String", mrb_obj_classname(mrb, value)); return mrb_nil_value(); } char *nam = mrb_string_value_ptr(mrb, name); char *val = mrb_string_value_ptr(mrb, value); if (setenv(nam, val, 1) != 0) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't change environment variable"); return mrb_nil_value();; } return value; }
int main(int argc, char** argv) { const char rite[] = "app.mrb"; mrb_state* mrb = mrb_open(); FILE* fp = fopen(rite, "r"); if (fp == NULL) { fprintf(stderr, "%s not found.\n", rite); fprintf(stderr, "`mruby/bin/mrbc app.rb` to create app.mrb file.\n"); exit(EXIT_FAILURE); } int n = mrb_read_irep_file(mrb, fp); fclose(fp); if (n < 0) { fprintf(stderr, "%s - irep load error.\n", rite); exit(EXIT_FAILURE); } mrb_run(mrb, mrb_proc_new(mrb, mrb->irep[n]), mrb_top_self(mrb)); if (argc < 2) { printf("Usage %s <environment>\n", argv[0]); return 0; } // AppSetting struct RClass* clz = mrb_class_get(mrb, "AppSetting"); mrb_value setting = mrb_obj_value(clz); // AppSetting.load(*targets) -> AppConfig mrb_value target = mrb_str_new(mrb, argv[1], strlen(argv[1])); mrb_value conf = mrb_funcall(mrb, setting, "load", 1, target); // AppConfig.#debug -> bool mrb_value debug = mrb_funcall(mrb, conf, "debug", 0); printf("debug: %d\n", mrb_type(debug) == MRB_TT_TRUE); // AppConfig.#timeout -> Integer mrb_value timeout = mrb_funcall(mrb, conf, "timeout", 0); printf("timeout: %d\n", timeout.value.i); // AppConfig.#title -> String mrb_value title = mrb_funcall(mrb, conf, "title", 0); printf("title: %s\n", mrb_string_value_ptr(mrb, title)); // AppConfig.#messages -> Array mrb_value messages = mrb_funcall(mrb, conf, "messages", 0); { // Array.#size -> Integer mrb_value len = mrb_funcall(mrb, messages, "size", 0); int i; for (i = 0; i < len.value.i; i++) { // Array.#at(nth) -> object mrb_value message = mrb_funcall(mrb, messages, "at", 1, mrb_fixnum_value(i)); printf("%s\n", mrb_string_value_ptr(mrb, message)); } } mrb_close(mrb); return 0; }
static mrb_value make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass) { mrb_value nstr, *ptr_members; mrb_sym id; long i, len; struct RClass *c; //OBJ_FREEZE(members); if (mrb_nil_p(name)) { c = mrb_class_new(mrb, klass); //mrb_make_metaclass(nstr, RBASIC(klass)->c); //mrb_class_inherited(klass, nstr); } else { /* old style: should we warn? */ name = mrb_str_to_str(mrb, name); id = mrb_to_id(mrb, name); if (!mrb_is_const_id(id)) { //mrb_name_error(id, "identifier %s needs to be constant", StringValuePtr(name)); mrb_name_error(mrb, id, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name)); } if (mrb_const_defined_at(mrb, klass, id)) { //mrb_warn("redefining constant Struct::%s", StringValuePtr(name)); mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name)); //?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } MRB_SET_INSTANCE_TT(c, MRB_TT_STRUCT); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern(mrb, "__members__"), members); mrb_define_class_method(mrb, c, "new", mrb_class_new_instance_m, ARGS_ANY()); mrb_define_class_method(mrb, c, "[]", mrb_class_new_instance_m, ARGS_ANY()); mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, ARGS_NONE()); //RSTRUCT(nstr)->basic.c->super = c->c; ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i< len; i++) { mrb_sym id = SYM2ID(ptr_members[i]); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { if (i < N_REF_FUNC) { mrb_define_method_id(mrb, c, id, (mrb_func_t)ref_func[i], 0); } else { mrb_define_method_id(mrb, c, id, mrb_struct_ref, 0); } mrb_define_method_id(mrb, c, mrb_id_attrset(id), (mrb_func_t)mrb_struct_set, 1); } } return nstr; }
static mrb_value make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass) { mrb_value nstr, *ptr_members; mrb_sym id; mrb_int i, len; struct RClass *c; if (mrb_nil_p(name)) { c = mrb_class_new(mrb, klass); } else { /* old style: should we warn? */ name = mrb_str_to_str(mrb, name); id = mrb_to_id(mrb, name); if (!mrb_is_const_id(id)) { mrb_raisef(mrb, E_NAME_ERROR, "identifier %s needs to be constant", mrb_string_value_ptr(mrb, name)); } if (mrb_const_defined_at(mrb, klass, id)) { mrb_warn("redefining constant Struct::%s", mrb_string_value_ptr(mrb, name)); //?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); } c = mrb_define_class_under(mrb, klass, RSTRING_PTR(name), klass); } MRB_SET_INSTANCE_TT(c, MRB_TT_ARRAY); nstr = mrb_obj_value(c); mrb_iv_set(mrb, nstr, mrb_intern2(mrb, "__members__", 11), members); mrb_define_class_method(mrb, c, "new", mrb_instance_new, ARGS_ANY()); mrb_define_class_method(mrb, c, "[]", mrb_instance_new, ARGS_ANY()); mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, ARGS_NONE()); //RSTRUCT(nstr)->basic.c->super = c->c; ptr_members = RARRAY_PTR(members); len = RARRAY_LEN(members); for (i=0; i< len; i++) { mrb_sym id = mrb_symbol(ptr_members[i]); if (mrb_is_local_id(id) || mrb_is_const_id(id)) { if (i < N_REF_FUNC) { mrb_define_method_id(mrb, c, id, ref_func[i], ARGS_NONE()); } else { mrb_define_method_id(mrb, c, id, mrb_struct_ref, ARGS_NONE()); } mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, ARGS_REQ(1)); } } return nstr; }
int main() { mrb_state* mrb = mrb_open(); // mrubyファイルをロードする FILE *fd = fopen("person.mrb", "r"); mrb_load_irep_file(mrb, fd); // *.rbを直接ロードする // FILE *fd = fopen("person.rb", "r"); // mrb_load_file(mrb, fd); // クラスオブジェクトを取得する struct RClass *person = mrb_class_get(mrb, "Person"); // 引数をmrb_valueに変換する mrb_value person_value = mrb_obj_value(person); mrb_value name_value = mrb_str_new(mrb, "naoty", 5); mrb_value age_value = mrb_fixnum_value(25); // Person#newを呼び出す mrb_value naoty = mrb_funcall(mrb, person_value, "new", 2, name_value, age_value); // Person#greetingを呼び出す mrb_value greeting_value = mrb_funcall(mrb, naoty, "greeting", 0); // 返り値をchar*に変換して出力する char *greeting = mrb_string_value_ptr(mrb, greeting_value); printf("%s\n", greeting); mrb_close(mrb); return 0; }
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)); }
mrb_value mrb_dir_entries(mrb_state* mrb, mrb_value self) { mrb_value entries = mrb_ary_new(mrb); mrb_value dirname; mrb_get_args(mrb, "S", &dirname); const char* name = mrb_string_value_ptr(mrb, dirname); tinydir_dir dir; if (tinydir_open(&dir, name) == -1) { mrb_raisef(mrb, E_RUNTIME_ERROR, "Error opening file: %S", mrb_str_new_cstr(mrb, name)); } while (dir.has_next) { tinydir_file file; tinydir_readfile(&dir, &file); mrb_ary_push(mrb, entries, mrb_str_new_cstr(mrb, file.name)); tinydir_next(&dir); } tinydir_close(&dir); return entries; }
/* * call-seq: * obj.send(symbol [, args...]) -> obj * obj.__send__(symbol [, args...]) -> obj * * Invokes the method identified by _symbol_, passing it any * arguments specified. You can use <code>__send__</code> if the name * +send+ clashes with an existing method in _obj_. * * class Klass * def hello(*args) * "Hello " + args.join(' ') * end * end * k = Klass.new * k.send :hello, "gentle", "readers" #=> "Hello gentle readers" */ static mrb_value mrb_f_send(mrb_state *mrb, mrb_value self) { mrb_value name, block, *argv; int argc; mrb_get_args(mrb, "o*&", &name, &argv, &argc, &block); return mrb_funcall_with_block(mrb,self, mrb_string_value_ptr(mrb, name), argc, argv, block); }
static mrb_value mrb_curses_addstr(mrb_state *mrb, mrb_value self) { mrb_value obj; mrb_get_args(mrb, "S", &obj); const char *body = mrb_string_value_ptr(mrb, obj); addstr(body); return mrb_bool_value(true); }
static mrb_value rb_load_compiled_mrb(mrb_state *mrb, mrb_value self) { mrb_value rstr; const char *str; mrb_get_args(mrb, "S", &rstr); str = mrb_string_value_ptr(mrb, rstr); return mrbcc_load_so(mrb, self, str); }
static mrb_sym mrb_sym_value(mrb_state *mrb, mrb_value val) { if(val.tt == MRB_TT_STRING) { return mrb_intern(mrb, RSTRING_PTR(val)); } else if(val.tt != MRB_TT_SYMBOL) { mrb_value obj = mrb_funcall(mrb, val, "inspect", 0); mrb_raise(mrb, E_TYPE_ERROR, "%s is not a symbol", mrb_string_value_ptr(mrb, obj)); } return mrb_symbol(val); }
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); }
static mrb_value mrb_curses_ewaddstr(mrb_state *mrb, mrb_value self) { if (echo_win == NULL) { return mrb_bool_value(false); } mrb_value obj; mrb_get_args(mrb, "S", &obj); const char *body = mrb_string_value_ptr(mrb, obj); waddstr(echo_win, body); return mrb_bool_value(true); }
int main() { mrb_state* mrb; int n; FILE* f; mrb_value ret; mrb = mrb_open(); f = fopen("test.rb", "r"); mrb_load_file(mrb, f); fclose(f); ret = mrb_funcall(mrb, mrb_top_self(mrb), "test", 1, mrb_fixnum_value(20) ); //mrb_define_method(mrb, mrb->kernel_module, "cursor_move", cursor_move, MRB_ARGS_REQ(2)); //------------------------------------------ int x, y; int key=' '; char *str; initscr(); keypad(stdscr, TRUE); setlocale(LC_ALL, ""); x = 0; y = 0; while (1) { key = getch(); ret = mrb_funcall(mrb, mrb_top_self(mrb), "evaluate", 1, mrb_fixnum_value(key) ); str = mrb_string_value_ptr(mrb, ret); addstr(str); if (key == 'q') break; switch (key) { case KEY_UP: y--; break; case KEY_DOWN: y++; break; case KEY_LEFT: x--; break; case KEY_RIGHT: x++; break; default : mvprintw(y, x++, "%c", key); break; } move(y, x); //mrb_load_string(mrb,"cursor_move(x, y);"); } endwin(); mrb_close(mrb); return (0); }
static mrb_value mrb_env_unsetenv(mrb_state *mrb, mrb_value name) { mrb_value val = mrb_env_getenv(mrb, name); if (mrb_nil_p(val)) { return mrb_nil_value(); } char *nam = mrb_string_value_ptr(mrb, name); if (unsetenv(nam) != 0) { mrb_raise(mrb, E_RUNTIME_ERROR, "can't delete environment variable"); return mrb_nil_value(); } return val; }
static mrb_value mrb_env_getenv(mrb_state *mrb, mrb_value name) { if (mrb_type(name) != MRB_TT_STRING) { mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %s into String", mrb_obj_classname(mrb, name)); return mrb_nil_value(); } char *nam = mrb_string_value_ptr(mrb, name); char *env = getenv(nam); if (env == NULL) { return mrb_nil_value(); } return mrb_str_new2(mrb, env); }
mrb_value mrb_dir_exists(mrb_state* mrb, mrb_value self) { mrb_value dirname; mrb_get_args(mrb, "S", &dirname); const char* name = mrb_string_value_ptr(mrb, dirname); tinydir_dir dir; if (tinydir_open(&dir, name) == -1) { return mrb_false_value(); } tinydir_close(&dir); return mrb_true_value(); }
void mrb_cmperr(mrb_state *mrb, mrb_value x, mrb_value y) { const char *classname; if (SPECIAL_CONST_P(y)) { y = mrb_inspect(mrb, y); //classname = StringValuePtr(y); classname = mrb_string_value_ptr(mrb, y); } else { classname = mrb_obj_classname(mrb, y); } mrb_raise(mrb, E_ARGUMENT_ERROR, "comparison of %s with %s failed", mrb_obj_classname(mrb, x), classname); }
//convert rbObj in RVector (assumed to be possible!!!) SEXP mrbArray2RVector(mrb_value rbobj) { SEXP ans; mrb_value arr,elt,tmp; //char *name; int n,i; if(!mrb_obj_is_kind_of(mrb,rbobj,mrb->array_class)) { if(!(mrb_obj_is_kind_of(mrb,rbobj,mrb->fixnum_class) || mrb_obj_is_kind_of(mrb,rbobj,mrb->float_class) || mrb_obj_is_kind_of(mrb,rbobj,mrb->string_class) || mrb_obj_is_kind_of(mrb,rbobj,mrb->true_class) || mrb_obj_is_kind_of(mrb,rbobj,mrb->false_class))) return R_NilValue; n=1; arr = mrb_ary_new_capa(mrb,1); mrb_ary_push(mrb,arr,rbobj); } else { arr=rbobj; n=RARRAY_LEN(rbobj); } //Rprintf("n=%d\n",n); elt=mrb_ary_entry(arr,0); if(mrb_type(elt)==MRB_TT_FLOAT) { PROTECT(ans=allocVector(REALSXP,n)); for(i=0;i<n;i++) { REAL(ans)[i]=mrb_float(mrb_ary_entry(arr,i)); } } else if(mrb_type(elt)==MRB_TT_FIXNUM) { PROTECT(ans=allocVector(INTSXP,n)); for(i=0;i<n;i++) { INTEGER(ans)[i]=mrb_int(mrb,mrb_ary_entry(arr,i)); } } else if(mrb_type(elt)==MRB_TT_TRUE || mrb_type(elt)==MRB_TT_FALSE) { PROTECT(ans=allocVector(LGLSXP,n)); for(i=0;i<n;i++) { LOGICAL(ans)[i]=(mrb_type(mrb_ary_entry(arr,i))==MRB_TT_FALSE ? FALSE : TRUE); } } else if(mrb_type(elt)==MRB_TT_STRING) { PROTECT(ans=allocVector(STRSXP,n)); for(i=0;i<n;i++) { tmp=mrb_ary_entry(arr,i); SET_STRING_ELT(ans,i,mkChar(mrb_string_value_ptr(mrb,tmp))); } } else ans=R_NilValue; UNPROTECT(1); return ans; }
mrb_value mrb_game_reload_file(mrb_state* mrb, mrb_value self) { mrb_value path; mrb_get_args(mrb, "S", &path); char* file_path = mrb_string_value_ptr(mrb, path); FILE* file = fopen(file_path, "r"); if (file == NULL) { printf("Error opening file: %s\n", file_path); return self; } mrb_load_file(mrb,file); fclose(file); return self; }
mrb_value qgame_shader_asset_load_from_file(mrb_state* mrb, mrb_value self) { mrb_value path; mrb_sym shader_type_sym; mrb_get_args(mrb, "nS", &shader_type_sym, &path); GLenum shader_type = shader_type_sym_to_enum(mrb, shader_type_sym); GLuint shader = glCreateShader(shader_type); if(shader == 0) { mrb_raisef(mrb, E_RUNTIME_ERROR, "Failed creating shader with type: %i", mrb_fixnum_value(shader_type)); return self; } char* shader_source = read_file(mrb_string_value_ptr(mrb, path)); glShaderSource(shader, 1, (const GLchar**)&shader_source, NULL); glCompileShader(shader); free(shader_source); GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint infoLogLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); char strInfoLog[infoLogLength + 1]; glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog); glDeleteShader(shader); shader = NULL; mrb_raisef(mrb, E_RUNTIME_ERROR, "Failed compiling shader '%S': %S", path, mrb_str_new_cstr(mrb, &strInfoLog)); return self; } mrb_value shader_id = mrb_fixnum_value(shader); mrb_iv_set(mrb, self, mrb_intern(mrb, "shader_id"), shader_id); return self; }
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; }
static const char *_mrb_string(mrb_state* mrb, mrb_value o) { return mrb_string_value_ptr(mrb, o); }
mrb_value qgame_texture_asset_load_from_file(mrb_state* mrb, mrb_value self) { GLuint texture; // This is a handle to our texture object SDL_Surface *surface; // This surface will tell us the details of the image GLenum texture_format; mrb_value path; mrb_get_args(mrb, "S", &path); char* file = mrb_string_value_ptr(mrb, path); if ( (surface = IMG_Load(file)) ) { // Check that the image's width is a power of 2 if ( (surface->w & (surface->w - 1)) != 0 ) { printf("warning: %s's width is not a power of 2\n", file); } // Also check if the height is a power of 2 if ( (surface->h & (surface->h - 1)) != 0 ) { printf("warning: %s's height is not a power of 2\n", file); } // get the number of channels in the SDL surface GLint nOfColors = surface->format->BytesPerPixel; if (nOfColors == 4) // contains an alpha channel { if (surface->format->Rmask == 0x000000ff) texture_format = GL_RGBA; else texture_format = GL_BGRA; } else if (nOfColors == 3) // no alpha channel { if (surface->format->Rmask == 0x000000ff) texture_format = GL_RGB; else texture_format = GL_BGRA; } else { printf("warning: the image is not truecolor.. this will probably break\n"); } // Have OpenGL generate a texture object handle for us glGenTextures( 1, &texture ); // Bind the texture object glBindTexture( GL_TEXTURE_2D, texture ); // Set the texture's stretching properties glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // Edit the texture object's image data using the information SDL_Surface gives us glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, surface->w, surface->h, 0, texture_format, GL_UNSIGNED_BYTE, surface->pixels ); GLenum err = glGetError(); if (err != GL_NO_ERROR) { printf("Error loading image into GL: %i\n", err); } mrb_value texture_id = mrb_fixnum_value(texture); mrb_iv_set(mrb, self, mrb_intern(mrb, "texture_id"), texture_id); mrb_value mrb_width = mrb_fixnum_value(surface->w); mrb_iv_set(mrb, self, mrb_intern(mrb, "@width"), mrb_width); mrb_value mrb_height = mrb_fixnum_value(surface->h); mrb_iv_set(mrb, self, mrb_intern(mrb, "@height"), mrb_height); } else { printf("SDL could not load image.bmp: %s\n", SDL_GetError()); } // Free the SDL_Surface only if it was successfully created if ( surface ) { SDL_FreeSurface( surface ); } return self; }