use vars qw/ $VERSION @EXPORT /;
-$VERSION = '0.05';
+$VERSION = '0.06';
@EXPORT = (qw/
T_SV
T_SVREF
T_AVREF
+ T_AVREF_REFCOUNT_FIXED
T_HVREF
+ T_HVREF_REFCOUNT_FIXED
T_CVREF
T_SYSRET_fail T_SYSRET_pass
T_UV
static intRefIv xst_anintrefiv;
static intOpq xst_anintopq;
+/* A different type to refer to for testing the different
+ * AV* and HV* typemaps */
+typedef AV AV_FIXED;
+typedef HV HV_FIXED;
+
/* Helper functions */
/* T_ARRAY - allocate some memory */
From the perl level this is a reference to a perl array.
From the C level this is a pointer to an AV.
+Note that this typemap does not decrement the reference count
+when returning an AV*. See also: T_AVREF_REFCOUNT_FIXED
+
=cut
AV *
OUTPUT:
RETVAL
+=item T_AVREF_REFCOUNT_FIXED
+
+From the perl level this is a reference to a perl array.
+From the C level this is a pointer to an AV. This is a fixed
+variant of T_AVREF that decrements the refcount appropriately
+when returning an AV*. Introduced in perl 5.15.4.
+
+=cut
+
+AV_FIXED*
+T_AVREF_REFCOUNT_FIXED( av )
+ AV_FIXED * av
+ CODE:
+ SvREFCNT_inc(av);
+ RETVAL = av;
+ OUTPUT:
+ RETVAL
+
=item T_HVREF
From the perl level this is a reference to a perl hash.
From the C level this is a pointer to an HV.
+Note that this typemap does not decrement the reference count
+when returning an HV*. See also: T_HVREF_REFCOUNT_FIXED
+
=cut
HV *
OUTPUT:
RETVAL
+=item T_HVREF_REFCOUNT_FIXED
+
+From the perl level this is a reference to a perl hash.
+From the C level this is a pointer to an HV. This is a fixed
+variant of T_HVREF that decrements the refcount appropriately
+when returning an HV*. Introduced in perl 5.15.4.
+
+=cut
+
+HV_FIXED*
+T_HVREF_REFCOUNT_FIXED( hv )
+ HV_FIXED * hv
+ CODE:
+ SvREFCNT_inc(hv);
+ RETVAL = hv;
+ OUTPUT:
+ RETVAL
+
+
=item T_CVREF
From the perl level this is a reference to a perl subroutine
}
}
-use Test::More tests => 84;
+use Test::More tests => 88;
use strict;
use warnings;
eval { T_SVREF( "fail - not ref" ) };
ok( $@ );
+
# T_AVREF - reference to a perl Array
print "# T_AVREF\n";
eval { T_AVREF( \$sv ) };
ok( $@ );
+# T_AVREF_REFCOUNT_FIXED - reference to a perl Array, refcount fixed
+print "# T_AVREF_REFCOUNT_FIXED\n";
+
+is( T_AVREF_REFCOUNT_FIXED(\@array), \@array);
+
+# Now test that a non array ref is rejected
+eval { T_AVREF_REFCOUNT_FIXED( \$sv ) };
+ok( $@ );
+
+
# T_HVREF - reference to a perl Hash
print "# T_HVREF\n";
ok( $@ );
+# T_HVREF_REFCOUNT_FIXED - reference to a perl Hash, refcount fixed
+print "# T_HVREF_REFCOUNT_FIXED\n";
+
+is( T_HVREF_REFCOUNT_FIXED(\%hash), \%hash);
+
+# Now test that a non hash ref is rejected
+eval { T_HVREF_REFCOUNT_FIXED( \@array ) };
+ok( $@ );
+
+
+
# T_CVREF - reference to perl subroutine
print "# T_CVREF\n";
my $sub = sub { 1 };
shortOPQ T_OPAQUE
shortOPQ * T_OPAQUEPTR
astruct * T_OPAQUEPTR
+AV_FIXED * T_AVREF_REFCOUNT_FIXED
+HV_FIXED * T_HVREF_REFCOUNT_FIXED
Time_t * T_PV
SV * T_SV
SVREF T_SVREF
+CV * T_CVREF
+
+# These are the backwards-compatibility AV*/HV* typemaps that
+# do not decrement refcounts. Locally override with
+# "AV* T_AVREF_REFCOUNT_FIXED" and/or
+# "HV* T_HVREF_REFCOUNT_FIXED" to get the fixed version.
AV * T_AVREF
HV * T_HVREF
-CV * T_CVREF
IV T_IV
UV T_UV
\"$var\");
}
} STMT_END
+T_AVREF_REFCOUNT_FIXED
+ STMT_START {
+ SV* const xsub_tmp_sv = $arg;
+ SvGETMAGIC(xsub_tmp_sv);
+ if (SvROK(xsub_tmp_sv) && SvTYPE(SvRV(xsub_tmp_sv)) == SVt_PVAV){
+ $var = (AV*)SvRV(xsub_tmp_sv);
+ }
+ else{
+ Perl_croak(aTHX_ \"%s: %s is not an ARRAY reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\");
+ }
+ } STMT_END
T_HVREF
STMT_START {
SV* const xsub_tmp_sv = $arg;
\"$var\");
}
} STMT_END
+T_HVREF_REFCOUNT_FIXED
+ STMT_START {
+ SV* const xsub_tmp_sv = $arg;
+ SvGETMAGIC(xsub_tmp_sv);
+ if (SvROK(xsub_tmp_sv) && SvTYPE(SvRV(xsub_tmp_sv)) == SVt_PVHV){
+ $var = (HV*)SvRV(xsub_tmp_sv);
+ }
+ else{
+ Perl_croak(aTHX_ \"%s: %s is not a HASH reference\",
+ ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+ \"$var\");
+ }
+ } STMT_END
T_CVREF
STMT_START {
SV* const xsub_tmp_sv = $arg;
$arg = newRV((SV*)$var);
T_AVREF
$arg = newRV((SV*)$var);
+T_AVREF_REFCOUNT_FIXED
+ $arg = newRV_noinc((SV*)$var);
T_HVREF
$arg = newRV((SV*)$var);
+T_HVREF_REFCOUNT_FIXED
+ $arg = newRV_noinc((SV*)$var);
T_CVREF
$arg = newRV((SV*)$var);
T_IV