Reputation: 15069
I'm using the C extension methods to create a new ruby array, but RARRAY_LEN is not getting set. Am I doing something wrong?
long int max = 4;
VALUE rAry;
rAry = rb_ary_new2(max);
printf("allocated: %lu\n", RARRAY_LEN(rAry));
output:
allocated: 0
Upvotes: 4
Views: 765
Reputation: 2914
From array.c
(Ruby 1.8.6):
#define RARRAY_LEN(s) (RARRAY(s)->len)
RARRAY(s)->len
is the same as Array#length
.
rb_ary_new2(4)
is not the same as Array.new(4)
.
VALUE
rb_ary_new2(len)
long len;
{
return ary_new(rb_cArray, len);
}
VALUE
rb_ary_new()
{
return rb_ary_new2(ARY_DEFAULT_SIZE);
}
ARY_DEFAULT_SIZE
is defined as 16
.
What is does is just allocate memory for an array - but doesn't populate it. Use it when you know the final size of your array so it doesn't have to be dynamically re-sized.
What you want to use for your intentions are rb_ary_new3
or rb_ary_new4
.
From Programming Ruby: The Pragmatic Programmer's Guide:
VALUE rb_ary_new3(long length, ...")
Returns a newArray
of the given length and populated with the remaining arguments.
VALUE rb_ary_new4(long length, VALUE *values")
Returns a newArray
of the given length and populated with the C array values.
Note that these functions require you to provide a value for each element. So you'd need to do something like: rAry = rb_ary_new3(4, Qnil, Qnil, Qnil, Qnil)
to replicate Array.new(4)
. If you provided less arguments you'd get strange behavior in Ruby. (No exceptions - despite the fact you get an invalid object.)
Upvotes: 2
Reputation: 15069
Apparently rb_ary_store(obj, index, val) needs to be used to increment RARRAY_LEN. It's strange that a method so crucial is basically undocumented.
Upvotes: 0