perlxs

How can I pass an array to a C function in Perl XS?


How can I pass Perl array by reference to C XS module?

my @array = ( 1..20 );

XSTEST::test_array_passing(\@array);

What do I do in XS so it sees the array?


Solution

  • XS can receive a ref to ARRAY as either an AV* or an SV*. The latter would have to be dereferenced to an AV*.

    use Inline C => DATA;
    @array = (1 .. 20);
    $r = sum_of_elements1(\@array);
    $s = sum_of_elements2(\@array);
    print "$r $s\n";  #  produces output: "210 210\n"
    __END__
    __C__
    double sum_of_elements1(AV* array)
    {
      int i;
      double sum = 0.0;
      for (i=0; i<=av_len(array); i++) {
        SV** elem = av_fetch(array, i, 0);
        if (elem != NULL)
          sum += SvNV(*elem);
      }
      return sum;
    }
    
    double sum_of_elements2(SV* array_ref)
    {
      AV* array;
      if (!SvROK(array_ref) || SvTYPE(SvRV(array_ref)) != SVt_PVAV)
        croak("expected ARRAY ref");
      array = (AV*) SvRV(array_ref);
      return sum_of_elements1(array);
    }
    

    The .xs file produced by this code declares:

    double
    sum_of_elements1 (array_ref)
            SV *    array_ref
    
    double
    sum_of_elements2 (array)
            AV *    array
    

    Edit: in sum_of_element2(), added the check that the *SV was a reference to an array.