http://www.perlmonks.org?node_id=123378


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

Maybe the casting of entry to an SV does the trick. newRC_inc can also take an AV as input.

Update: Tested the following... too lazy for XS, so Inline:

use Data::Dumper; $ref = testRV( 'monks' ); print Dumper( $ref ); use Inline C => <<'END_OF_C' SV* testRV(char* dirname){ SV* record[2]; AV *entry, *ret_val; SV* retarray; int i = 0; ret_val = newAV(); while (i<10) { record[0] = newSVpv(dirname, 0); record[1] = newSViv(i); entry = av_make(2, record); av_push(ret_val, newRV_inc( entry)); i++; } retarray=newRV_noinc( ret_val); return retarray; } END_OF_C #results in: $VAR1 = [ [ 'monks', '0' ], [ 'monks', 1 ], [ 'monks', 2 ], ...
In other words, just a 2D array as you wanted. BTW, Inline didn't complain about the AV* 's, but than, maybe those warnings were suppressed?

So I think Fastolfe has pinpointed it, when he noticed you exc'd the sub in array context...

If you really want to output arrays from C, you need to push your items on the stack.

Replies are listed 'Best First'.
Re: Re: XS routine returns an extra depth of array refs
by mugwumpjism (Hermit) on Nov 05, 2001 at 23:34 UTC
    If you really want to output arrays from C, you need to push your items on the stack.

    Right, that's the ticket. This seems to work the way I want:

    #include <sys/types.h> #include <dirent.h> #include <stdio.h> void readdir_inode(dirname) char* dirname INIT: struct dirent *ent; DIR* dir; SV* record[2]; AV *entry, *ret_val; PPCODE: dir = opendir(dirname); if (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); PUSHs(newRV_noinc(av_make(2, record))); } closedir(dir); }

    At least, I hope that last "newRV_noinc" shouldn't be a "newRV_inc"!

      It should be newRV_inc. :-)

      Only with inline the refcounter of the SV gets auto-incremented. With XS you have to that yourself.

      Update: For clarity, only the refcounter of the SV that gets returned! Other SV*'s you have to inc manually!

        The whole reason I'm not using Inline is because I want to be able to compile this as a module and not have it try to compile stuff at run time!
Re: Re: XS routine returns an extra depth of array refs
by mugwumpjism (Hermit) on Nov 05, 2001 at 22:33 UTC

    All the casting does is remove this warning during compilation:

    ReadDir.xs: In function `XS_ReadDir_readdir_inode': ReadDir.xs:43: warning: passing arg 1 of `Perl_newRV' from incompatibl +e pointer type