Search code examples
crubyruby-c-extension

How do I access a ruby array from my c extension?


I'm getting this error

ev.c:11: error: subscripted value is neither array nor pointer

for this line

printf("%d\n", pairs[0][0]);

In this code

static VALUE EV;
static VALUE PairCounter;

static VALUE 
sort_pairs_2(VALUE self) {
    VALUE pairs;

    pairs = rb_ivar_get(self, rb_intern("pairs"));
    printf("%d\n", pairs[0][0]);
  return Qnil;
}

void Init_ev() {
    rb_eval_string("require './lib/ev/pair_counter'");
    VALUE PairCounter = rb_path2class("EV::PairCounter");
    rb_define_method(PairCounter, "sort_pairs_2", sort_pairs_2, 0);
}

Am I using self incorrectly, and rb_ivar_get is not actually pointing to the PairCounter class?


Solution

  • I'm pretty sure you need to use the RARRAY_PTR macro on pairs to get at the underlying array; for example, the internal implementation of Array#push (for 1.9.2) looks like this:

    static VALUE
    rb_ary_push_1(VALUE ary, VALUE item)
    {
        long idx = RARRAY_LEN(ary);
    
        if (idx >= ARY_CAPA(ary)) {
            ary_double_capa(ary, idx); 
        }
        RARRAY_PTR(ary)[idx] = item;
        ARY_SET_LEN(ary, idx + 1);   
        return ary;
    }
    

    The if just sorts out any necessary resizing, then there's RARRAY_PTR(ary)[idx] for accessing a single slot in the array.

    I don't have any official references to back this up but hopefully this will be of some use.