Estoy tratando de escribir un código XS que expone piezas de una biblioteca a código Perl como una interfaz de flujo que se puede escribir en. La función siguiente get_stream
se supone que es un constructor que prepara y devuelve un objeto PerlIO. Pensé que solo necesitaba los métodos Write
y Close
, así que dejé en blanco todas las demás ranuras de función.¿Por qué este código XS que devuelve PerlIO * tiene fugas?
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
Cuando uso la interfaz proporcionada como esto ...
{
my $fh = MyLib::get_stream($lib_ctx);
print $fh "x" x 300;
}
... mylib_write
la función es llamada, por lo que tengo no totalmente atornilla hasta ahora. (He verificado esto insertando instrucciones printf de depuración). Sin embargo, me gustaría que el objeto PerlIO se cierre cuando $fh
sale del alcance, tal y como funcionan las cosas con filehandles regulares creados por open
. Pero por el momento, la función mylib_close
solo se invoca durante el apagado del intérprete.
llamando directamente close
funciona bien, el establecimiento de $fh
a undef
no se .
ACTUALIZACIÓN: Siguiendo el consejo de Ikegami, solía Devel::Peek::Dump
y sv_dump
, y se informó de que el asa volvió get_stream
función es una "RV" que apunta a una SV = PVGV(...)
. El glob (PVGV
) tiene su contador de referencia establecido en 3, lo que no parece correcto.
I añadió
CLEANUP:
SvREFCNT_dec (SvRV (ST(0)));
SvREFCNT_dec (SvRV (ST(0)));
que cura el síntoma: La función close
se llama cuando $fh
sale del ámbito en el extremo del bloque. Pero todavía no entiendo el problema subyacente.
Esto se genera el código C para la sección OUTPUT
:
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);
¿Cómo termina contador de referencia del GV a las 3?
ug, toda nueva pregunta en la misma en el mismo puesto – ikegami