calling a swig generated function

M

Michael Hale

I have a library that I wrapped with SWIG. One of the SWIG generated
functions looks like this:

static VALUE
_wrap_NSCalculateGap(int argc, VALUE *argv, VALUE self) {
int arg1 ;
int arg2 ;
unsigned long arg3 ;
double arg4 ;
unsigned long *arg5 = (unsigned long *) 0 ;
int arg6 ;
int arg7 ;
int arg8 ;
int result;
VALUE vresult = Qnil;

if ((argc < 8) || (argc > 8))
rb_raise(rb_eArgError, "wrong # of arguments(%d for 8)",argc);
arg1 = NUM2INT(argv[0]);
arg2 = NUM2INT(argv[1]);
arg3 = NUM2ULONG(argv[2]);
arg4 = (double) NUM2DBL(argv[3]);
SWIG_ConvertPtr(argv[4], (void **) &arg5, SWIGTYPE_p_unsigned_long,
1);
arg6 = NUM2INT(argv[5]);
arg7 = NUM2INT(argv[6]);
arg8 = NUM2INT(argv[7]);
result =
(int)NSCalculateGap(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8);

vresult = INT2NUM(result);
return vresult;
}

How should I call this function from ruby? I am having problems with
arg5. Here is my current attempt:

pulGap = 0
Smartlib::NSCalculateGap(iMode, iSpeed, ulPacketLength, dValue,
pulGap, hub, slot, port)

However this gives me the following error:

TypeError: wrong argument type Fixnum (expected Data)

Also here is an example from the library documetation:

int iMode = PERCENT_LOAD_TO_GAP_BITS
int iSpeed = SPEED_10GHZ
unsigned long ulPacketLength = 100
double dValue = 95.5
unsigned long ulGap = 0;
NSCalculateGap(iMode,iSpeed,dValue,&ulGap,iHub,iSlot,iPort);

Thanks, Michael

"OS X: because it was easier to make UNIX user-friendly than to fix
Windows"
 
L

Lyle Johnson

I have a library that I wrapped with SWIG. One of the SWIG generated
functions looks like this:

<snip>

I'm guessing that the fifth argument is declared as a pointer to an
unsigned long, correct? The problem is that SWIG doesn't know which
one of the many interpretations of that to use. In this case, it
appears that the NSCalculateGap() function uses that unsigned long
pointer argument to return a value (i.e. for output), but as far as
SWIG knows you could be passing in a single unsigned long value, or
even an array of unsigned longs, as input.
How should I call this function from ruby?

You're going to need to use a typemap of some kind to let SWIG know
that, in this case, that unsigned long pointer argument is actually an
output value. Depending on how you've written your SWIG interface
file, you'll want to do something like this:

// Include declarations for output typemaps from the SWIG library
%include typemaps.i

// Apply SWIG's OUTPUT typemap for unsigned long values to the
"ulGap" argument
%apply unsigned long *OUTPUT { unsigned long ulGap; }

// Here's what I would guess the actual function declaration looks like...
void NSCalculateGap(int iMode, int iSpeed, unsigned long
ulPacketLength, double dValue, unsigned long *ulGap, int iHub, int
iSlot, int iPort);

Now, when you call this function from Ruby you will only pass in the
seven input arguments, and catch the output value as the method
result, e.g.

ulGap = Smartlib::NSCalculateGap(iMode, iSpeed, ulPacketLength,
dValue, hub, slot, port)

For more information, see the "Argument Handling" chapter of the SWIG manual:

http://www.swig.org/Doc1.3/Arguments.html

Hope this helps,

Lyle
 
M

Michael Hale

Thank you for the suggestion. I was able to get my code to work with
the following in my smartlib.i file:

%apply unsigned long *OUTPUT { unsigned long *pulGap };

Now I call the function like this:

NSCalculateGap(iMode, iSpeed, ulPacketLength, dValue, hub, slot, port)

And get back an array with the first element being the original return
value and the second being the value of the pulGap pointer. Like this:

[0,1273]

BTW here is the method definition from my header file:

int DLL_EXPORT NSCalculateGap(int iMode, int iSpeed,
unsigned long ulPacketLength,
double dValue,
unsigned long *pulGap,
int iHub, int iSlot, int iPort);


<snip>

I'm guessing that the fifth argument is declared as a pointer to an
unsigned long, correct? The problem is that SWIG doesn't know which
one of the many interpretations of that to use. In this case, it
appears that the NSCalculateGap() function uses that unsigned long
pointer argument to return a value (i.e. for output), but as far as
SWIG knows you could be passing in a single unsigned long value, or
even an array of unsigned longs, as input.


You're going to need to use a typemap of some kind to let SWIG know
that, in this case, that unsigned long pointer argument is actually an
output value. Depending on how you've written your SWIG interface
file, you'll want to do something like this:

// Include declarations for output typemaps from the SWIG library
%include typemaps.i

// Apply SWIG's OUTPUT typemap for unsigned long values to the
"ulGap" argument
%apply unsigned long *OUTPUT { unsigned long ulGap; }

// Here's what I would guess the actual function declaration looks
like...
void NSCalculateGap(int iMode, int iSpeed, unsigned long
ulPacketLength, double dValue, unsigned long *ulGap, int iHub, int
iSlot, int iPort);

Now, when you call this function from Ruby you will only pass in the
seven input arguments, and catch the output value as the method
result, e.g.

ulGap = Smartlib::NSCalculateGap(iMode, iSpeed, ulPacketLength,
dValue, hub, slot, port)

For more information, see the "Argument Handling" chapter of the SWIG
manual:

http://www.swig.org/Doc1.3/Arguments.html

Hope this helps,

Lyle
"OS X: because it was easier to make UNIX user-friendly than to fix
Windows"
 
L

Lyle Johnson

Thank you for the suggestion. I was able to get my code to work with
the following in my smartlib.i file:

%apply unsigned long *OUTPUT { unsigned long *pulGap };

Now I call the function like this:

NSCalculateGap(iMode, iSpeed, ulPacketLength, dValue, hub, slot, port)

And get back an array with the first element being the original return
value and the second being the value of the pulGap pointer. Like this:

[0,1273]

OK, good!
BTW here is the method definition from my header file:

int DLL_EXPORT NSCalculateGap(int iMode, int iSpeed,
unsigned long ulPacketLength,
double dValue,
unsigned long *pulGap,
int iHub, int iSlot, int iPort);

Yes, I couldn't tell from your previous example (in the original post)
what kind of return value, if any, NSCalculateGap() was declared to
have -- so I guess a void return type. If you only want the wrapped
version of NSCalculateGap() to return a single value (the gap) and not
that two-element array, you might be able to do something like this:

%extend {
unsigned long NSCalculateGap(int iMode, int iSpeed, unsigned
long ulPacketLength, double dValue, int iHub, int iSlot, int iPort) {
int iResult;
unsigned long ulGap;
iResult = NSCalculateGap(iMode, iSpeed, ulPacketLength,
dValue, &ulGap, iHub, iSlot, iPort);
return ulGap;
}
}

In other words, we're introducing a helper function in the middle that
calls the "real" NSCalculateGap() function and ignores its integer
return value. If that integer return value shouldn't be ignored --
say, because it is an error code or something -- you might want to
check it first and raise an exception, or whatever makes sense for
your application.

Hope this helps,

Lyle
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top