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.