Tuesday March 22, 2005 Converting C arrays to Perl lists
Here is a short example of XS dealing with C arrays. I assume that you followed
direction in the previous section and have a populated ext/Test/XS directory.
Suppose that we have the following C function:
void intlist(int size, int *output)
{
for (i = 0; i < size; i++)
output[i] = i;
}
and we would like to get access to it from Perl. We will start by creating xs_test.c file together with our XS::Test module, containing the function above. We will also add
void intlist(int, int *);
line to the "xs_test.h" file.
Now we can write XS glue code to provide an interface with the C function. What
we will do there is get every entry from the C array and push it onto the Perl
stack and return it as a Perl list. We need to use the PPCODE directive to do
this:
void
intlist(size)
int size;
PREINIT:
int *a;
PPCODE:
if (size > 0 && New(0, a, size, int) != NULL) {
int i;
(void)intlist(size, a);
/* Create enough space on the stack */
EXTEND(SP, size);
for (i = 0; i < size; i++)
PUSHs(sv_2mortal(newSVnv(a[i])));
}
If the size argument is zero or negative or we can't allocate memory the function will return empty list to the caller.
To test the function let's add few tests to the XS-test.t file:
my @l = intlist 5;
ok(eq_array(\@l, [0, 1, 2, 3, 4]), 'Correct intlist array') or
diag("invalid result of intlist 5: \@l = @l");
my @l1 = intlist(-1);
my $l1 = @l1;
is($l1, 0, 'Invalid list is empty') or
diag("The returned list is @l1");
We are using the Test::More(1) eq_array function to compare two arrays.
Everything works fine so far. We can run
$ make test
in the module directory and all tests pass.
Technorati Tag: Perl
( Mar 22 2005, 06:31:09 PM PST ) Permalink Comments [0]