Weblog

All | CMT | General | NUMA | OpenSolaris | Perl | Photo | Programmers Desk | STREAMS
« Previous day (Apr 7, 2005) | Main | Next day (Apr 9, 2005) »
20050408 Friday April 08, 2005

Converting C arrays to Perl arrays in XS: Continuation

Converting C arrays to Perl arrays in XS: Continuation

In the previous example we created a Perl function intlist() which returned a list of integers starting from 0.

Here is a simple example:

  $ perl -Mblib -MXS::Test \
        -e 'print join(" ", intlist 5), "\n"';
  0 1 2 3 4

What happens if we call the intlist function in scalar context?

  $ perl -Mblib -MXS::Test \
        -e 'print scalar intlist 5, "\n"';
  4

It prints the last value! It does the same thing when getting scalar value of a list:

  $ perl -e 'print scalar (0,1,2,3,4), "\n"'
  4

The reason is that it treats the value in brackets as the comma operator which returns the last value. Now what if we want to return something different when the function is called in scalar context? For example, we may want to return the total number of elements or some other value. In Perl we can use wantarray() function for that purpose. There is a similar way in XS code.

Let us rewrite the intlist XS definition:

  void
  intlist(size)
        int size;
  PREINIT:
        int *a;
  PPCODE:
        if (GIMME_V == G_SCALAR) {
                if (size >= 0)
                        XSRETURN_IV(size);
                else
                        XSRETURN_UNDEF;
        }
        if (size > 0 && New(0, a, size, int) != NULL) {
                int i;
                intlist(size, a);
                EXTEND(SP, size);
                for (i = 0; i < size; i++)
                        PUSHs(sv_2mortal(newSVnv(a[i])));
        }

The expression GIMME_V == G_SCALAR is true when the function is called in scalar context. In this case we return the size specified as an immediate return value using the XSRETURN_IV macro or return undef value if size is negative. Now, if we repeat the example above, we get what we expect:

  $ perl -Mblib -MXS::Test \
        -e 'print scalar intlist 5, "\n"';
  5

Or, if we specify a negative value

  $ perl -Mblib -MXS::Test -MData::Dumper \
        -e 'print Dumper(scalar intlist -5), "\n"';
  $VAR1 = undef;

Technorati Tag:

( Apr 08 2005, 08:20:46 PM PDT ) Permalink Comments [1]

Calendar

RSS Feeds

Search

Links

Navigation

Referers