spacepille has asked for the wisdom of the Perl Monks concerning the following question:

The following does not work with a tied handle.
perlio = IoIFP( sv_2io( sv ) ); PerlIO_read( perlio, ... );
Does anybody know how to access tied handles from XS? Thank you.

Replies are listed 'Best First'.
Re: tied handle in xs
by plobsing (Friar) on Oct 03, 2008 at 04:19 UTC
    I have no experience working with tied objects in XS, but I imagine it would be similar to whatever the perl core does.

    First lookup what op does the same thing you want to do. In this case, read (called pp_read in C and located in mathoms.c). It delegates to pp_sysread in pp_sys.c.

    The definition of this op is in the section following PP(pp_sysread)

    The section that handles tied handles is:
    if ((PL_op->op_type == OP_READ || PL_op->op_type == OP_SYSREAD) && gv && (io = GvIO(gv)) ) { const MAGIC * mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar); if (mg) { SV *sv; PUSHMARK(MARK-1); *MARK = SvTIED_obj((SV*)io, mg); ENTER; call_method("READ", G_SCALAR); LEAVE; SPAGAIN; sv = POPs; SP = ORIGMARK; PUSHs(sv); RETURN; } }
      I have no experience working with tied objects in XS, but I imagine it would be similar to whatever the perl core does.
      There's better ways, perlXStut: EXAMPLE 9 Passing open files to XSes.
        I've read that. It suggests using typemaps for PerlIO objects (my first resort).

        However, looking at the T_IN and T_INOUT typemaps, they both do $var = IoIFP(sv_2io($arg)).

        That apparently isn't working for spacepille. So I looked for other options.
      big thank you, it works...
      IO *io = sv_2io( sv ); PerlIO *perlio = IoIFP( io ); if( perlio != NULL ) { PerlIO_read( perlio, ... ); } else { const MAGIC *mg = SvTIED_mg( (SV *) io, 'q' ); if( mg != NULL ) { sv = SvTIED_obj( (SV *) io, mg ); // call the READ method with sv as object... } else { Perl_croak( aTHX_ "invalid IO handle" ); } }