I am trying to write some XS code that exposes pieces a library to
Perl code as a stream interface that can be written to. The
get_stream
function below is supposed to be a constructor that
prepares and returns a PerlIO object. I figured that I only need the
Write
and Close
methods, so I left all other function slots blank.
typedef struct {
struct _PerlIO base;
mylib_context* ctx;
} PerlIOmylib;
/* [...] */
PERLIO_FUNCS_DECL(PerlIO_mylib_funcs) = {
.fsize = sizeof(PerlIO_funcs),
.name = "mylib",
.size = sizeof(PerlIOmylib,
.Write = mylib_write,
.Close = mylib_close,
};
/* XS below */
PerlIO*
get_stream (SV* context_obj)
CODE:
mylib_context* ctx = (mylib_context*) SvIV (SvRV (context_obj));
PerlIO* f = PerlIO_allocate (aTHX);
f = PerlIO_push (aTHX, f, PERLIO_FUNCS_CAST(&PerlIO_mylib_funcs), "a", NULL);
PerlIOSelf(f, PerlIOmylib)->ctx = ctx;
PerlIOBase(f)->flags |= PERLIO_F_OPEN;
RETVAL = f;
OUTPUT:
RETVAL
When I use the provided interface like this...
{
my $fh = MyLib::get_stream($lib_ctx);
print $fh "x" x 300;
}
... the mylib_write
function gets called, so I haven't totally
screwed up so far. (I verified this by inserting debug printf
statements.) However, I would like the PerlIO object to be closed when
$fh
goes out of scope, just the way things work with regular
filehandles created by open
. But at the moment, the mylib_close
function is only called during interpreter shutdown.
Directly calling close
works fine, setting $fh
to undef
does
not.
UPDATE: Following ikegami's advice, I used Devel::Peek::Dump
and sv_dump
and found out that the handle returned get_stream
function is a "RV"
which points to a SV = PVGV(...)
. The glob (PVGV
) has its
reference counter set to 3 which doesn't seem right.
I added
CLEANUP:
SvREFCNT_dec (SvRV (ST(0)));
SvREFCNT_dec (SvRV (ST(0)));
which cures the symptom: The close
function is called when $fh
goes out of scope at the end of the block. But I still don't quite
understand the underlying problem.
This is the C code generated for the OUTPUT
section:
ST(0) = sv_newmortal();
{
GV *gv = newGVgen("MyLib");
if (do_open(gv, "+<&", 3, FALSE, 0, 0, RETVAL) )
sv_setsv(ST(0), sv_bless(newRV((SV*)gv), gv_stashpv("MyLib",1)));
else
ST(0) = &PL_sv_undef;
}
XSRETURN(1);
How does the GV's reference count end up at 3?