Friday April 08, 2005 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: Perl
( Apr 08 2005, 08:20:46 PM PDT ) Permalink Comments [1]