Last active
December 24, 2015 12:59
-
-
Save wrl/6801788 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
** keeping track of objects that exist in both C and mruby is tricky! in | |
** situations where you're binding to a library which maintains its own | |
** internal lists of child objects (say, in a UI toolkit, a container | |
** object with a list of contained widgets), you want to do the least | |
** amount of bookkeeping possible, lest you do your bookkeeping wrong. | |
** | |
** here's a simple solution. it works by mapping a cptr to a ruby object, | |
** which preferably you'd use to wrap around said cptr with a MRB_TT_DATA | |
** object. the way you use it is simple: whenever you get a pointer back | |
** from the API you're wrapping, look it up in this here GC map. if it | |
** exists, there's your wrapped object. if it doesn't, you can take the | |
** pointer and wrap an object around it, then store it in the map. | |
** | |
** there are two benefits to this method: | |
** - ruby-allocated objects will not be garbage collected while they're in | |
** the map, since instance variables are traversed by the garbage | |
** collector. | |
** | |
** - for a given cptr, you keep a reference around to the same ruby | |
** object, and you can easily wrap around objects which were not | |
** allocated in ruby but that you'd still like to interact with. | |
** | |
** released under the unlicense <http://unlicense.org/> | |
*/ | |
struct gc_map { | |
mrb_value hash; | |
}; | |
static int | |
gc_map_init(mrb_state *mrb, struct gc_map *m, mrb_value on_obj) | |
{ | |
m->hash = mrb_hash_new(mrb); | |
mrb_iv_set(mrb, on_obj, mrb_intern2(mrb, "__gc_map__", 10), m->hash); | |
return 0; | |
} | |
static mrb_value | |
gc_map_get(mrb_state *mrb, struct gc_map *m, void *p) | |
{ | |
return mrb_hash_get(mrb, m->hash, mrb_cptr_value(mrb, p)); | |
} | |
static void | |
gc_map_set(mrb_state *mrb, struct gc_map *m, void *p, | |
mrb_value object) | |
{ | |
mrb_hash_set(mrb, m->hash, mrb_cptr_value(mrb, p), object); | |
} | |
static mrb_value | |
gc_map_delete(mrb_state *mrb, struct gc_map *m, void *p) | |
{ | |
return mrb_hash_delete_key(mrb, m->hash, mrb_cptr_value(mrb, p)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment