From: Kurt Dresner Date: 2004-11-23T05:49:53+09:00 Subject: Re: SWIG and Arrays (of ints) So here's what I have right now. The only thing that's missing is the stuff to fix the last function. %module unh_cmac %include typemaps.i #define ALBUS 65 #define RECTANGULAR 82 #define LINEAR 76 #define SPLINE 83 #define CUSTOM 67 #define VTRUE 1 #define VFALSE 0 %typemap(ruby,in) (int num_state, int *qnt_state) { int i; if (!rb_obj_is_kind_of($input,rb_cArray)) rb_raise(rb_eArgError, "Expected Array of Integers"); $1 = RARRAY($input)->len; $2 = malloc($1*sizeof(int)); for (i=0; i<$1; ++i) ($2)[i] = NUM2INT(RARRAY($input)->ptr[i]); } %typemap(freearg) (int size, int *ary) { if ($2) free($2); } %typemap(ruby,out) int { if($1 == 0) { $result = Qnil; } else { $result = INT2NUM($1); } } int allocate_cmac(int num_state, int *qnt_state, int num_resp, int num_cell, int memory, int rfield_shape, int collision_flag); %typemap(ruby,in) (int *state) { int i; int length; if (!rb_obj_is_kind_of($input,rb_cArray)) rb_raise(rb_eArgError, "Expected Array of Integers"); length = RARRAY($input)->len; $1 = malloc(length*sizeof(int)); for (i=0; iptr[i]); } %typemap(freearg) (int *state) { if ($1) free($1); } %typemap(ruby,in) (int *respns) { int i; int length; if (!rb_obj_is_kind_of($input,rb_cArray)) rb_raise(rb_eArgError, "Expected Array of Integers"); length = RARRAY($input)->len; $1 = malloc(length*sizeof(int)); for (i=0; iptr[i]); } %typemap(freearg) (int *respns) { if ($1) free($1); } %typemap(ruby,out) int { if($1 == 0) { $result = Qfalse; } else { $result = Qtrue; } } int train_cmac(int cmac_id, int *state, int *respns, int beta1, int beta2); /* Need stuff here */ int cmac_response(int cmac_id, int *state, int *respns); -Kurt On Mon, 22 Nov 2004 13:09:03 -0600, Kurt Dresner wrote: > Here are the actual functions I need to wrap: > > /* This one allocates a cmac, which is the thing I'm going to be > using. I tell it how many > * states it has, how many responses it has, and some other > parameters. The typemap you > * provided I think will work rather well for this function. > */ > int allocate_cmac(int num_state, int *qnt_state, > int num_resp, int num_cell, > int memory, int rfield_shape, > int collision_flag); > > /* With this function, I provide the ID of the cmac that was returned > to me in the allocate > * function. I then provide two arrays: the input states and the > desired responses. These > * have to be of the sizes num_state and num_resp from the last > function. I think a similar > * typemap will work just fine, since the C code presumably knows the > size of the arrays. > * I just won't provide it. > */ > int train_cmac(int cmac_id, int *state, int *respns, int beta1, int beta2); > > /* This is the one I'm stuck on. I need to provide the ID, which will > work, and then an array > * of state ints. That will work too, as in the last one. Now, > however, I need to provide > * an array for the response. This array is then filled up with the > response. Two things are > * confusing me. I should probably do some sort of argout so I can > get both the int > * (success/failure) return value (which I can probably map to > true/nil right?) and the array > * return value. The thing is, I don't know how to get it to create a > Ruby array for this > * return value, since in the interface code, I don't know how big the > array is. The C code > * knows (presumably - I didn't write it). So I don't know how to > write the argout to take care > * of it. I have no idea what to do with this. > */ > int cmac_response(int cmac_id, int *state, int *respns); > > Any ideas? > > -Kurt > > > > > On Sun, 21 Nov 2004 22:58:07 +0900, Tobias Peters > wrote: > > Kurt Dresner wrote: > > > > > > > Hi all, > > > > > > I'm trying to get SWIG to create a wrapper for some C code. > > > Specifically, there are several functions that take, as parameters, an > > > int* (they also take the length of the array). I don't know how to do > > > the typemap for this - I want to be able to write > > > > > > My_module.my_c_function([1,2,3]) > > > > > > for the corresponding C function > > > > > > void my_c_function(int size, int* ary) > > > > > > Additionally, one of the functions takes an integer array as a > > > parameter, and I'd like it instead to return an array in Ruby (full of > > > Nums). I know how to get it to return the argument (instead of doing > > > the pointer passing thing), but then it just thinks I want to pass it > > > an integer instead of an array of integers. > > > > > > Anyone have any idea how to help me? Everything I've seen pertains to > > > char** and I'm not sure how to convert it to work how I want with > > > int*. > > > > Passing an array of integers from Ruby to C with SWIG requires > > multi-argument "in" and "freearg" typemaps: > > > > %typemap(ruby,in) (int size, int *ary) { > > int i; > > if (!rb_obj_is_kind_of($input,rb_cArray)) > > rb_raise(rb_eArgError, "Expected Array of Integers"); > > $1 = RARRAY($input)->len; > > $2 = malloc($1*sizeof(int)); > > for (i=0; i<$1; ++i) > > ($2)[i] = NUM2INT(RARRAY($input)->ptr[i]); > > } > > %typemap(freearg) (int size, int *ary) { > > if ($2) free($2); > > } > > > > There's room for improvement in handling (or better: preventing) > > exceptions raised from NUM2INT (proper error message and deallocation of > > C array). > > > > Regarding output: It's not clear to me if you want in/out semantics or > > output only. I think you can achieve in/out with an additional > > multi-argument "argout" typemap. Output only implementation depends on > > which function is responsible for allocating/freeing the array and which > > is responsible for determining the array's size. You may need an > > additional "arginit" typemap for this one. > > > > Tobias > > > > >