Skip to content

Instantly share code, notes, and snippets.

@v2e4lisp
Last active August 29, 2015 14:03
Show Gist options
  • Save v2e4lisp/c387a9b97b22772cf461 to your computer and use it in GitHub Desktop.
Save v2e4lisp/c387a9b97b22772cf461 to your computer and use it in GitHub Desktop.
ruby ext memo

RUBY.ext

Test a ruby object is truthy | Tield block

  • RTEST(VALUE rb_obj)
  • rb_yield(VALUE rb_obj) yield a value to given block. For multiple values, rb_assoc_new them first

example

VALUE assoc, v;
val = dbm_fetch(dbm, key);
assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
		     rb_tainted_str_new(val.dptr, val.dsize));
v = rb_yield(assoc);
if (RTEST(v)) {
    rb_ary_push(new, assoc);
}

Convert c struct to ruby object

Date_Wrap_Struct(Value klass, void(*mark)(), void(*free)(), void *ptr)

create a instance object of klass, and set instance's DATA_PTR to ptr

example

static VALUE
fdbm_alloc(VALUE klass)
{
    return Data_Wrap_Struct(klass, 0, free_dbm, 0);
}

mark should mark all the fields whose types are from ruby in a C struct so that ruby's GC will be able to free their memory.

example of mark

void ParserWrapper_mark(void *data) {
  if(data) {
    ParserWrapper *wrapper = (ParserWrapper *) data;
    rb_gc_mark_maybe(wrapper->request_url);
    rb_gc_mark_maybe(wrapper->upgrade_data);
    rb_gc_mark_maybe(wrapper->headers);
    rb_gc_mark_maybe(wrapper->on_message_begin);
    rb_gc_mark_maybe(wrapper->on_headers_complete);
    rb_gc_mark_maybe(wrapper->on_body);
    rb_gc_mark_maybe(wrapper->on_message_complete);
    rb_gc_mark_maybe(wrapper->callback_object);
    rb_gc_mark_maybe(wrapper->last_field_name);
    rb_gc_mark_maybe(wrapper->curr_field_name);
  }
}

Convert ruby object to a C struct.

Data_Get_Struct(VALUE obj, struct s_type, s_type s_inst)

get obj's DATA_PTR and assign to s_inst

example

Data_Get_Struct(obj, struct dbmdata, dbmp);
if (dbmp == 0)
    return Qtrue;
if (dbmp->di_dbm == 0)
    return Qtrue;

Ruby class create a object

  1. call class alloc function to create a instance, (The DATE_PTR of the instance should be set either here or in the initialize method
  2. call the instance's initialize method

rb_define_alloc_func register alloc function for class

example

rb_define_alloc_func(rb_cDBM, fdbm_alloc);

Set object data pointer | Alloc memory for c struct in ruby way

  • DATA_PTR(VALUE obj) = c_data
  • ALLOC(struct_type)

example

dbmp = ALLOC(struct dbmdata);
DATA_PTR(obj) = dbmp;
dbmp->di_dbm = dbm;
dbmp->di_size = -1;

Free

macro xfree prevent from freeing memory of NULL pointer.

ruby nil check | block_given? | yield | ensure

example

VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);

if (NIL_P(fdbm_initialize(argc, argv, obj))) {
    return Qnil;
}

if (rb_block_given_p()) {
    return rb_ensure(rb_yield, obj, fdbm_close, obj);
}

Get ruby string pointer and string length

  • RSTRING_PTR
  • RSTRING_LEN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment