From: Konrad Meyer Date: 2007-08-10T02:57:09+09:00 Subject: Re: SWIG question: how to return an array from C to Ruby ? --nextPart1208633.uKhTcj21FC Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline On Thursday 09 August 2007 03:20:04 am Joachim (M=FCnchen) wrote: > I need to make some C functions available to Ruby. One of them sets an > array of doubles. I want to return this array to Ruby. >=20 > On the C side: >=20 > data_reader.c: > #include "hardwaredriver.h" > ... > void read_data( double *data ) > { > for( i=3D0; i<8; ++i ) > data[i] =3D .... // get values from hardware driver > } >=20 > On the Ruby side, I would like to obtain the following >=20 > irb> require "data_reader" > true > irb> arr =3D Data_reader.read_data > [ 0.0, 0.1, ... ] # arr now contains eight Floats >=20 >=20 > Question 1: > Do I understand correctly that there are basically two different ways > to proceed ?: > (a) wrapping the C code with SWIG, > (b) converting the C code to an explicit Ruby extension as > described in the Book: http://www.rubycentral.com/pickaxe/ext_ruby.html >=20 > IF the answer is yes, THEN While I don't know much (anything) about SWIG, C code needs to be wrapped as an extension to Ruby or indirectly wrapped via Inline for it to be used by ruby code. > Question 2: > How do I return an array through C->SWIG-> Ruby ? >=20 > Web search gave me some hints on how to do it in the opposite > direction, using typemap(in); but it seems not trivial to invert > to typemap(out). >=20 > Thanks in advance, Joachim I'd recommend Inline for this, as it provides nice ruby->C parameter conversions. To return ruby array data, you need a variable of type VALUE, which is a generic ruby object container. It's also probably easiest if you know how long the array will be in advance (in fact I don't know what to do otherwise). ex: #define ARR_LEN 31 VALUE ary; double data[ARR_LEN]; ... /* do your hw->data[] processing here */ ary =3D rb_ary_new2(ARR_LEN); for(i =3D 0; i < ARR_LEN; i++) RARRAY(ary)->ptr[i] =3D rb_float_new(data[i]); RARRAY(ary)->len =3D ARR_LEN; return ary; Something like that ought to do the trick. Happy ruby-ing! =2D-=20 Konrad Meyer http://konrad.sobertillnoon.com/ --nextPart1208633.uKhTcj21FC Content-Type: application/pgp-signature; name=signature.asc Content-Description: This is a digitally signed message part. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.7 (GNU/Linux) iD8DBQBGu1VuCHB0oCiR2cwRAjTNAJ9+dCKeBRS4bwun1p0gRsIGqL0K0QCfS58x K2Hni2yGZIn+WJeo2veWNkE= =fAag -----END PGP SIGNATURE----- --nextPart1208633.uKhTcj21FC--