On Thu, 2 Aug 2001, Evan Zane Macosko wrote:
> I was wondering if I could get some help with the XS syntax for passing
> array references from Perl to an extension written in C. Basically, I
> have a two dimensional matrix of real values in Perl, and I want some
> hefty calculations done on it in C, since it's faster. However, XS won't
> let me declare an array as an argument of the C function. Also, I can't
> seem to use pointers, since it only lets me use pointers of type char as
> arguments. Any ideas?
Yes, I have some code somewhere that takes a hash reference as an argument,
I'll see if I can dig it up...
> Also, if I want to return a matrix of values, must I mess with the stack,
> or is there a quicker/easier way?
You could allocate an AV (Array Value) and populate it with AV's [ie
construct an array of arrays] and then take a reference to the first AV
and return it.
Looking at some of my old code, your XS prototype should be something like:
SV *
data_wrangler (ARG)
SV * ARG
And your implementation (assuming it's in a separate .c file) should go
something like:
SV * data_wrangler (SV *d_in)
{
AV * data_in;
AV * data_out;
int ** c_data;
if( !SvROK( d_in ) || ( SvTYPE( SvRV( d_in ) ) != SVt_PVAV ) )
{
/* not a reference, or not a reference to an array */
/* die bleeding in a gutter, or something... */
}
data_in = (AV *)SvRV( d_in );
munge_av_into_int_thingy( c_data, data_in );
/* data mangling */
/* Now you can create a new AV to return: */
data_out = newAV();
/* copy the data back into it in some way, then return a ref to it */
munge_int_thingy_into_av( c_data, data_in );
return (SV *) newRV_noinc( (SV*) data_out )
}
Alternatively, you could write the data back into your in array, overwriting
it's previous contents, in which case, iirc, you wouldn't have to return
anything.
perldoc perlguts, perldoc perlxs, and perldoc perlxstut are your friends.
In particular, for creating an array with a number of per SV's already in
existence:
AV* av_make(I32 num, SV **ptr);
and:
void av_push(AV*, SV*);
SV* av_pop(AV*);
SV* av_shift(AV*);
void av_unshift(AV*, I32 num);
HTH
(filtered through my ever failing memory, so treat w. caution :)
--
Vivek