I am trying to write some XS code that provides a part of the library for Perl code as a stream interface that can be written to. get_stream function below should be a constructor that prepares and returns a PerlIO object. I decided that I only needed Write and Close , so I left all the other function slots empty.
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, }; 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; }
... calls the mylib_write function, so I haven't completely so far. (I checked this by inserting debug printf). However, I would like the PerlIO object to be closed when $fh goes beyond just how everything works with regular files created using open . But at the moment, the mylib_close function is called only when the interpreter is turned off.
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 get_stream function returned by the descriptor is "RV", which points to a SV = PVGV(...) . Glob ( PVGV ) has its link count set to 3, which seems to be wrong.
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 do not 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 GV link counting end at 3?