From: Noah Easterly Date: 2007-08-07T23:20:01+09:00 Subject: Re: how to scan a RARRAY ??? On Aug 7, 8:57 am, unbewust wrote: > 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 ;-) > > 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