Thank,

Regards

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;
     }
   }




--
---
==========================================================================
 Patrick DUPRÉ                      |   |
 Department of Chemistry            |   |    Phone: (44)-(0)-1904-434384
 The University of York             |   |    Fax:   (44)-(0)-1904-432516
 Heslington                         |   |
 York YO10 5DD  United Kingdom      |   |    email: [EMAIL PROTECTED]
==========================================================================
-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
http://learn.perl.org/

Reply via email to