Weblog

All | CMT | General | NUMA | OpenSolaris | Perl | Photo | Programmers Desk | STREAMS
« Previous day (Mar 21, 2005) | Main | Next day (Mar 23, 2005) »
20050322 Tuesday March 22, 2005

Converting C arrays to Perl lists

Converting C arrays to Perl arrays in XS

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:

( Mar 22 2005, 06:31:09 PM PST ) Permalink Comments [0]

Calendar

RSS Feeds

Search

Links

Navigation

Referers