|
|
Patrick Dupre wrote:
> Hello,
>
> I am trying to pass a array of references on array to a c subroutine:
> my @set_2d = ([0.0, 1.0], [1.1, 2.2], [3.1, 4.4]) ;
> test::test(\@set_2d) ;
>
> in xs I put:
>
> typedef double floatArray ;
>
> void * floatArrayPtr (int num) {
> SV * mortal ;
> mortal = sv_2mortal (NEWSV (0, num * sizeof (floatArray))) ;
> return SvPVX (mortal) ;
> }
>
> double
> spectrum_2d (avref)
> AV * avref
> PREINIT:
> int len, ncols;
> int i, j ;
> SV ** elem ;
> floatMatrix *matrix ;
> AV** row ;
> CODE:
> len = av_len (avref) + 1 ;
> printf ("spectrum_2d: %d\n", len) ;
> ncols = 2 ;
> matrix = floatMatrixPtr (len) ;
> for (i = 0 ; i < len ; i++) {
> matrix [i] = floatArrayPtr (ncols) ;
> }
> for (i = 0 ; i < len ; i++) {
> row = av_fetch (avref, i , 0) ;
> if (row =! NULL) {
> for (j = 0 ; j < ncols ; j++) {
> elem = av_fetch (*row, j , 0) ;
> if (elem == NULL) {
> matrix [i] [j] = 0 ;
> }
> else {
> matrix [i] [j] = SvNV (*elem) ;
> }
> }
> }
> }
> RETVAL = 0 ;
> OUTPUT:
> RETVAL
>
> But it does not work,
> If somebody could tell me what is wrong !
OK, the main problem is that
row = av_fetch(avref, i , 0);
returns a **SV that is a reference to an array, not an array. So when you go
ahead to write
elem = av_fetch (*row, j , 0);
you're passing a *SV instead of a *AV. You need to dereference it like
rowref = av_fetch(avref, i , 0);
row = (AV *)SvRV(*rowref);
elem = av_fetch (row, j , 0);
Below is a working XS file.
HTH,
Rob
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
typedef double floatArray;
void *floatArrayPtr(int num)
{
SV *mortal = NEWSV(0, num * sizeof(floatArray));
sv_2mortal(mortal);
return SvPVX(mortal);
}
typedef floatArray *floatMatrix;
void *floatMatrixPtr(int num)
{
SV *mortal = NEWSV(0, num * sizeof(floatMatrix));
sv_2mortal(mortal);
return SvPVX(mortal);
}
MODULE = Arrays PACKAGE = Arrays
void
spectrum_2d(avref)
AV *avref
PREINIT:
int nrows, ncols;
int i, j;
AV *row;
SV **rowref, **elem;
floatMatrix *matrix;
CODE:
if (avref == NULL || SvTYPE(avref) != SVt_PVAV)
return;
nrows = av_len(avref) + 1;
matrix = floatMatrixPtr(nrows);
for (i = 0; i < nrows; i++) {
rowref = av_fetch(avref, i, 0);
if (rowref == NULL || !SvROK(*rowref))
{
matrix[i] = NULL;
continue;
}
row = (AV *)SvRV(*rowref);
ncols = av_len(row) + 1;
matrix[i] = floatArrayPtr(ncols);
for (j = 0; j < ncols; j++)
{
elem = av_fetch(row, j , 0);
if (SvNOK(*elem)) matrix[i][j] = SvNV(*elem);
else if (SvIOK(*elem)) matrix[i][j] = SvIV(*elem);
else matrix[i][j] = 0;
}
}
|
|