[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

SWIG and Arrays (of ints

Kurt Dresner

11/20/2004 8:04:00 PM

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*.

TIA,

Kurt


3 Answers

Tobias Peters

11/21/2004 1:50:00 PM

0

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

Kurt Dresner

11/22/2004 7:09:00 PM

0

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
<tpeters@invalid.uni-oldenburg.de> 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
>
>


Kurt Dresner

11/22/2004 8:50:00 PM

0

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; i<length; ++i)
($1)[i] = NUM2INT(RARRAY($input)->ptr[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; i<length; ++i)
($1)[i] = NUM2INT(RARRAY($input)->ptr[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 <omega697@gmail.com> 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
> <tpeters@invalid.uni-oldenburg.de> 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
> >
> >
>