dwww Home | Manual pages | Find package

IO::WrapTie(3pm)      User Contributed Perl Documentation      IO::WrapTie(3pm)

NAME
       IO::WrapTie - wrap tieable objects in IO::Handle interface

       This is currently Alpha code, released for comments.
         Please give me your feedback!

SYNOPSIS
       First of all, you'll need tie(), so:

          require 5.004;

       Function interface (experimental).  Use this with any existing class...

          use IO::WrapTie;
          use FooHandle;                  ### implements TIEHANDLE interface

          ### Suppose we want a "FooHandle->new(&FOO_RDWR, 2)".
          ### We can instead say...

          $FH = wraptie('FooHandle', &FOO_RDWR, 2);

          ### Now we can use...
          print $FH "Hello, ";            ### traditional operator syntax...
          $FH->print("world!\n");         ### ...and OO syntax as well!

       OO interface (preferred).  You can inherit from the "Slave" in
       IO::WrapTie mixin to get a nifty new_tie() constructor...

          #------------------------------
          package FooHandle;                        ### a class which can TIEHANDLE

          use IO::WrapTie;
          @ISA = qw(IO::WrapTie::Slave);            ### inherit new_tie()
          ...

          #------------------------------
          package main;

          $FH = FooHandle->new_tie(&FOO_RDWR, 2);   ### $FH is an IO::WrapTie::Master
          print $FH "Hello, ";                      ### traditional operator syntax
          $FH->print("world!\n");                   ### OO syntax

       See IO::Scalar as an example.  It also shows you how to create classes
       which work both with and without 5.004.

DESCRIPTION
       Suppose you have a class "FooHandle", where...

       •   "FooHandle"  does  not inherit from IO::Handle. That is, it performs
           file handle-like I/O, but to something other than an underlying file
           descriptor. Good examples are IO::Scalar (for printing to a  string)
           and IO::Lines (for printing to an array of lines).

       •   "FooHandle"  implements  the  "TIEHANDLE"  interface  (see perltie).
           That is, it provides methods "TIEHANDLE", "GETC", "PRINT", "PRINTF",
           "READ", and "READLINE".

       •   "FooHandle" implements the traditional OO  interface  of  FileHandle
           and  IO::Handle.  i.e.,  it contains methods like "getline", "read",
           "print", "seek", "tell", "eof", etc.

       Normally, users of your class would have two options:

       •   Use only OO syntax, and forsake named I/O operators like "print".

       •   Use with tie, and forsake treating it as a first-class object (i.e.,
           class-specific methods can only be invoked  through  the  underlying
           object via "tied"... giving the object a "split personality").

       But now with IO::WrapTie, you can say:

           $WT = wraptie('FooHandle', &FOO_RDWR, 2);
           $WT->print("Hello, world\n");   ### OO syntax
           print $WT "Yes!\n";             ### Named operator syntax too!
           $WT->weird_stuff;               ### Other methods!

       And  if  you're authoring a class like "FooHandle", just have it inherit
       from "IO::WrapTie::Slave" and that first line becomes even prettier:

           $WT = FooHandle->new_tie(&FOO_RDWR, 2);

       The bottom line: now, almost any class can look and work exactly like an
       IO::Handle and be used both with OO and non-OO file handle syntax.

HOW IT ALL WORKS
   The data structures
       Consider this example code, using classes in this distribution:

           use IO::Scalar;
           use IO::WrapTie;

           $WT = wraptie('IO::Scalar',\$s);
           print $WT "Hello, ";
           $WT->print("world!\n");

       In it, the "wraptie" function creates a data structure as follows:

                                 * $WT is a blessed reference to a tied filehandle
                     $WT           glob; that glob is tied to the "Slave" object.
                      |          * You would do all your i/o with $WT directly.
                      |
                      |
                      |     ,---isa--> IO::WrapTie::Master >--isa--> IO::Handle
                      V    /
               .-------------.
               |             |
               |             |   * Perl i/o operators work on the tied object,
               |  "Master"   |     invoking the C<TIEHANDLE> methods.
               |             |   * Method invocations are delegated to the tied
               |             |     slave.
               `-------------'
                      |
           tied(*$WT) |     .---isa--> IO::WrapTie::Slave
                      V    /
               .-------------.
               |             |
               |   "Slave"   |   * Instance of FileHandle-like class which doesn't
               |             |     actually use file descriptors, like IO::Scalar.
               |  IO::Scalar |   * The slave can be any kind of object.
               |             |   * Must implement the C<TIEHANDLE> interface.
               `-------------'

       NOTE: just as an IO::Handle is really just  a  blessed  reference  to  a
       traditional  file  handle  glob.  So  also,  an "IO::WrapTie::Master" is
       really just a blessed reference to a file handle  glob  which  has  been
       tied to some "slave" class.

   How "wraptie" works
       1.  The  call  to  function  "wraptie(SLAVECLASS, TIEARGS...)" is passed
           onto     IO::WrapTie::Master::new().       Note      that      class
           "IO::WrapTie::Master" is a subclass of IO::Handle.

       2.  The  "IO::WrapTie::Master->new"  method  creates  a  new  IO::Handle
           object, re-blessed into class "IO::WrapTie::Master". This object  is
           the master, which will be returned from the constructor. At the same
           time...

       3.  The  "new"  method  also  creates  the slave: this is an instance of
           "SLAVECLASS" which is created by tying the  master's  IO::Handle  to
           "SLAVECLASS" via "tie".  This call to "tie" creates the slave in the
           following manner:

       4.  Class  "SLAVECLASS" is sent the message "TIEHANDLE"; it will usually
           delegate this to  "SLAVECLASS->new(TIEARGS)",  resulting  in  a  new
           instance of "SLAVECLASS" being created and returned.

       5.  Once both master and slave have been created, the master is returned
           to the caller.

   How I/O operators work (on the master)
       Consider using an i/o operator on the master:

           print $WT "Hello, world!\n";

       Since  the  master  $WT  is  really a "blessed" reference to a glob, the
       normal Perl I/O operators like "print" may be used  on  it.   They  will
       just operate on the symbol part of the glob.

       Since the glob is tied to the slave, the slave's "PRINT" method (part of
       the "TIEHANDLE" interface) will be automatically invoked.

       If  the slave is an IO::Scalar, that means "PRINT" in IO::Scalar will be
       invoked, and that method happens to delegate to the  "print"  method  of
       the  same  class.   So  the  real  work is ultimately done by "print" in
       IO::Scalar.

   How methods work (on the master)
       Consider using a method on the master:

           $WT->print("Hello, world!\n");

       Since the master $WT is blessed into  the  class  "IO::WrapTie::Master",
       Perl  first attempts to find a "print" method there.  Failing that, Perl
       next attempts to find a "print" method in the super  class,  IO::Handle.
       It  just  so  happens  that  there  is such a method; that method merely
       invokes the "print" I/O operator on the self object...   and  for  that,
       see above!

       But  let's  suppose  we're  dealing  with  a  method which isn't part of
       IO::Handle... for example:

           my $sref = $WT->sref;

       In this case, the intuitive behavior is to have the master delegate  the
       method  invocation  to  the slave (now do you see where the designations
       come  from?).   This  is  indeed  what  happens:   "IO::WrapTie::Master"
       contains an "AUTOLOAD" method which performs the delegation.

       So:  when  "sref" can't be found in IO::Handle, the "AUTOLOAD" method of
       "IO::WrapTie::Master"  is  invoked,  and  the   standard   behavior   of
       delegating  the  method to the underlying slave (here, an IO::Scalar) is
       done.

       Sometimes, to get this to work  properly,  you  may  need  to  create  a
       subclass  of "IO::WrapTie::Master" which is an effective master for your
       class, and do the delegation there.

NOTES
       Why not simply use the object's OO interface?

       Because that means forsaking the use of named  operators  like  "print",
       and  you  may need to pass the object to a subroutine which will attempt
       to use those operators:

           $O = FooHandle->new(&FOO_RDWR, 2);
           $O->print("Hello, world\n");  ### OO syntax is okay, BUT....

           sub nope { print $_[0] "Nope!\n" }
        X  nope($O);                     ### ERROR!!! (not a glob ref)

       Why not simply use tie()?
           Because (1) you have to use "tied" to invoke methods in the object's
       public interface (yuck), and (2) you may need to pass the tied symbol to
       another subroutine which will attempt to treat it in  an  OO-way...  and
       that will break it:

           tie *T, 'FooHandle', &FOO_RDWR, 2;
           print T "Hello, world\n";   ### Operator is okay, BUT...

           tied(*T)->other_stuff;      ### yuck! AND...

           sub nope { shift->print("Nope!\n") }
        X  nope(\*T);                  ### ERROR!!! (method "print" on unblessed ref)

       Why a master and slave?

           Why not simply write C<FooHandle> to inherit from L<IO::Handle?>
       I tried this, with an implementation similar to that of L<IO::Socket>.
       The problem is that I<the whole point is to use this with objects
       that don't have an underlying file/socket descriptor.>.
       Subclassing L<IO::Handle> will work fine for the OO stuff, and fine with
       named operators I<if> you C<tie>... but if you just attempt to say:

           $IO = FooHandle->new(&FOO_RDWR, 2);
           print $IO "Hello!\n";

       you get a warning from Perl like:

           Filehandle GEN001 never opened

       because  it's  trying  to  do  system-level  I/O  on  an (unopened) file
       descriptor.  To avoid this, you apparently have to "tie"  the  handle...
       which  brings  us  right  back  to  where  we  started!   At  least  the
       IO::WrapTie mixin lets us say:

           $IO = FooHandle->new_tie(&FOO_RDWR, 2);
           print $IO "Hello!\n";

       and so is not too bad.  ":-)"

WARNINGS
       Remember: this stuff is for doing FileHandle-like I/O on things  without
       underlying file descriptors.  If you have an underlying file descriptor,
       you're better off just inheriting from IO::Handle.

       Be  aware  that  new_tie()  always  returns  an  instance  of  a kind of
       IO::WrapTie::Master... it does not return an instance of the  I/O  class
       you're tying to!

       Invoking some methods on the master object causes "AUTOLOAD" to delegate
       them  to  the  slave  object...  so  it looks like you're manipulating a
       "FooHandle" object directly, but you're not.

       I have not explored all the ramifications of this use  of  "tie".   Here
       there be dragons.

AUTHOR
       Eryq     (eryq@zeegee.com).      President,    ZeeGee    Software    Inc
       (http://www.zeegee.com).

CONTRIBUTORS
       Dianne Skoll (dfs@roaringpenguin.com).

COPYRIGHT & LICENSE
       Copyright (c) 1997 Erik (Eryq) Dorfman, ZeeGee Software, Inc. All rights
       reserved.

       This program is free software; you can redistribute it and/or modify  it
       under the same terms as Perl itself.

perl v5.38.2                       2024-07-31                  IO::WrapTie(3pm)

Generated by dwww version 1.16 on Tue Dec 16 05:22:09 CET 2025.