Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
Just another Perl shrine
 
PerlMonks  

Re: XS routine returns an extra depth of array refs

by jeroenes (Priest)
on Nov 05, 2001 at 22:28 UTC ( #123378=note: print w/ replies, xml ) Need Help??


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.


Comment on Re: XS routine returns an extra depth of array refs
Download Code
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
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!

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://123378]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (10)
As of 2014-04-25 08:57 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (585 votes), past polls