in reply to Re: XS routine returns an extra depth of array refs
in thread XS routine returns an extra depth of array refs

You hit the nail right on the head... I had the second, but Dumper \@a instead of Dumper $a[0], and my test code was assuming I was returning a list. Hate it when that happens ;-)

OK, so now at least I have it returning something sensible, which is always good. In which case, the question is why does this:

AV * readdir_inode(dirname) char* dirname INIT: struct dirent *ent; DIR* dir; SV* record[2]; AV *entry, *ret_val; CODE: RETVAL = newAV(); dir = opendir(dirname); if (!dir) perror("Cannot open dir"); while ((ent=readdir(dir))) { printf("%ld %x\n", ent->d_ino, ent->d_name); record[0] = newSVpv(ent->d_name, 0); record[1] = newSViv((IV)ent->d_ino); entry = av_make(2, record); av_push(RETVAL, newRV_inc((SV*) entry)); } closedir(dir); /*RETVAL=*ret_val;*/ /*RETVAL=newRV_inc((SV*) ret_val);*/ OUTPUT: RETVAL

Return an extra level of arrays?

The calling code:

my @ents = readdir_inode("."); print Dumper @ents;

The output:

$VAR1 = [ [ '.', 67586 ], [ '..', 255604
...

Replies are listed 'Best First'.
Re: Re: Re: XS routine returns an extra depth of array refs
by Fastolfe (Vicar) on Nov 06, 2001 at 02:17 UTC
    When you use RETVAL, XS builds it in such a way that it's functionally the same as the first item on the return stack. Thus, you've effectively stuck an AV into $ents[0], which I'm guessing Perl DWIM's here and turns it into a reference to an array. Hence the additional level of references.

    The correct way (I believe) to return a list in this situation is to declare your function with a return type of void and simply push each element onto the return stack instead of trying to return an array, using PUSHs I think.