How to scan a RARRAY?

from ruby.h :

struct RArray {
struct RBasic basic;
long len;
union {
long capa;
VALUE shared;
} aux;
VALUE *ptr;
};

my module make use of :
VALUE m_set_icon(VALUE self, VALUE src_path, VALUE dst_pathes[])

dst_pathes is a T_ARRAY

int len = RARRAY(dst_pathes)->len;
printf(“len = %d\n”, len);
char *cdst_pathes[len];

how to duplicated the VALUE (shared) from the struct RArray into
cdst_pathes (an Array of char *) ???

i don’t see how to use the VALUE *ptr, ie. in my case :
RARRAY(dst_pathes)->ptr

ruby side :

require ‘rseticon’

include RSetIcon

puts "RSetIcon : version = " + version()
puts "RSetIcon : set_icon(“aIcon.icns”, [“un”, “deux”, "trois
"]) = " + set_icon(“aIcon.icns”, [“un”, “deux”, “trois”]).to_s

gives the obvious result : [un, deux, trois].

“un”, “deux”, “trois” will be the pathes of files where we want to
apply the icon “aIcon.icns” (first arg of set_icon).

then, i want to retrieve, in the C side as a CString the pathes where
to apply the icon.

i don’t see how to use RARRAY(dst_pathes)->ptr to scan the VALUEs (in
the union aux) ???

thanks in advance :wink:

Yvon

On Aug 7, 8:57 am, unbewust [email protected] wrote:

include RSetIcon
then, i want to retrieve, in the C side as a CString the pathes where
to apply the icon.

i don’t see how to use RARRAY(dst_pathes)->ptr to scan the VALUEs (in
the union aux) ???

thanks in advance :wink:

Yvon

RArray->ptr is a (VALUE *) pointer to the the first VALUE stored in
the ruby array.
RArray->len is a count of the number of VALUEs stored in the ruby
array.
The VALUEs are stored sequentially.

From README.EXT (section 1.3)
| For example, RSTRING(str)->len' is the way to get the size of the | Ruby String object. The allocated region can be accessed by | RSTRING(str)->ptr’. For arrays, use RARRAY(ary)->len' and | RARRAY(ary)->ptr’ respectively.

You shouldn’t need to access the union aux to get to the array values.

For example, with example_ext.c:
| #include “ruby.h”
|
| /* print out all the ruby strings in the args array /
| static VALUE my_func( VALUE receiver, VALUE args )
| {
| int i;
| for (i = 0; i < RARRAY(args)->len; i++)
| {
| if (TYPE( RARRAY(args)->ptr[i] ) == T_STRING )
| {
| printf(“args[%d]: found string "%s"\n”, i,
RSTRING( RARRAY(args)->ptr[i] )->ptr );
| }
| else
| {
| printf(“args[%d]: did not find string\n”, i);
| }
| }
| return Qnil;
| }
|
| static VALUE my_init( VALUE self )
| {
| return self;
| }
|
| VALUE cMyClass;
| void Init_example_ext(void)
| {
| /
define MyClass as a ruby class /
| cMyClass = rb_define_class(“MyClass”, rb_cObject);
|
| /
define an initializer for MyClass /
| rb_define_method(cMyClass, “initialize”, my_init, 0);
|
| /
define my_meth as an instance method of MyClass /
| /
dump all the arguments to my_meth into a ruby array, and pass it
to my_func */
| rb_define_method(cMyClass, “my_meth”, my_func, -2);
| }

I can do
| require ‘example_ext’
| x = MyClass.new
| x.my_meth( “un”, “deux”, “trois”, “quatre”, “cinq”, [], “sept”,
“huit”, x )

and see
| args[0]: found string “un”
| args[1]: found string “deux”
| args[2]: found string “trois”
| args[3]: found string “quatre”
| args[4]: found string “cinq”
| args[5]: did not find string
| args[6]: found string “sept”
| args[7]: found string “huit”
| args[8]: did not find string

On 8/7/07, unbewust [email protected] wrote:

};

my module make use of :
VALUE m_set_icon(VALUE self, VALUE src_path, VALUE dst_pathes[])

VALUE m_set_icon(VALUE self, VALUE src_path, VALUE dst_pathes)

dst_pathes is a T_ARRAY

int len = RARRAY(dst_pathes)->len;
printf(“len = %d\n”, len);
char *cdst_pathes[len];

how to duplicated the VALUE (shared) from the struct RArray into
cdst_pathes (an Array of char *) ???

int len = RARRAY(dst_pathes)->len;
char* cdst_pathes[len];

long ii;
for (ii = 0; ii < len; ii++) {
VALUE str = rb_ary_entry( dst_pathes, ii );
cdst_pathes[ii] = StringValueCStr( str );
}

rb_ary_entry will return the VALUE from the Array at the given index.

StringValueCStr will check that the given VALUE is a String, and then
it will return the pointer of that String. This will not give you
copy, so the memory is still owned by the Ruby interpreter, and it
will be garbage collected if the original String object goes out of
scope. You might need to use memcopy to get a copy of the string that
will not be garbage collected – just depends on how long you’re going
to need a reference to the data.

Take a look at the Ruby source code for more methods for working with
Arrays and Strings. ruby.h and intern.h

rb_ary_ ← methods that operate on Array objects
rb_string_ ← methods that operate on String objects

Blessings,
TwP

On 7 août, 17:12, “Tim P.” [email protected] wrote:

    long capa;

dst_pathes is a T_ARRAY

it will return the pointer of that String. This will not give you
rb_string_ ← methods that operate on String objects

Blessings,
TwP

OK fine thanks, I’ve found it myself :wink: