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([EMAIL PROTECTED]) ;
> 
> 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;
      }
    }



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/


Reply via email to