1IO::WrapTie(3) User Contributed Perl Documentation IO::WrapTie(3)
2
3
4
6 IO::WrapTie - wrap tieable objects in IO::Handle interface
7
8 This is currently Alpha code, released for comments.
9 Please give me your feedback!
10
12 First of all, you'll need tie(), so:
13
14 require 5.004;
15
16 Function interface (experimental). Use this with any existing class...
17
18 use IO::WrapTie;
19 use FooHandle; ### implements TIEHANDLE interface
20
21 ### Suppose we want a "FooHandle->new(&FOO_RDWR, 2)".
22 ### We can instead say...
23
24 $FH = wraptie('FooHandle', &FOO_RDWR, 2);
25
26 ### Now we can use...
27 print $FH "Hello, "; ### traditional operator syntax...
28 $FH->print("world!\n"); ### ...and OO syntax as well!
29
30 OO interface (preferred). You can inherit from the "Slave" in
31 IO::WrapTie mixin to get a nifty new_tie() constructor...
32
33 #------------------------------
34 package FooHandle; ### a class which can TIEHANDLE
35
36 use IO::WrapTie;
37 @ISA = qw(IO::WrapTie::Slave); ### inherit new_tie()
38 ...
39
40
41 #------------------------------
42 package main;
43
44 $FH = FooHandle->new_tie(&FOO_RDWR, 2); ### $FH is an IO::WrapTie::Master
45 print $FH "Hello, "; ### traditional operator syntax
46 $FH->print("world!\n"); ### OO syntax
47
48 See IO::Scalar as an example. It also shows you how to create classes
49 which work both with and without 5.004.
50
52 Suppose you have a class "FooHandle", where...
53
54 • "FooHandle" does not inherit from IO::Handle. That is, it performs
55 file handle-like I/O, but to something other than an underlying
56 file descriptor. Good examples are IO::Scalar (for printing to a
57 string) and IO::Lines (for printing to an array of lines).
58
59 • "FooHandle" implements the "TIEHANDLE" interface (see perltie).
60 That is, it provides methods "TIEHANDLE", "GETC", "PRINT",
61 "PRINTF", "READ", and "READLINE".
62
63 • "FooHandle" implements the traditional OO interface of FileHandle
64 and IO::Handle. i.e., it contains methods like "getline", "read",
65 "print", "seek", "tell", "eof", etc.
66
67 Normally, users of your class would have two options:
68
69 • Use only OO syntax, and forsake named I/O operators like "print".
70
71 • Use with tie, and forsake treating it as a first-class object
72 (i.e., class-specific methods can only be invoked through the
73 underlying object via "tied"... giving the object a "split
74 personality").
75
76 But now with IO::WrapTie, you can say:
77
78 $WT = wraptie('FooHandle', &FOO_RDWR, 2);
79 $WT->print("Hello, world\n"); ### OO syntax
80 print $WT "Yes!\n"; ### Named operator syntax too!
81 $WT->weird_stuff; ### Other methods!
82
83 And if you're authoring a class like "FooHandle", just have it inherit
84 from "IO::WrapTie::Slave" and that first line becomes even prettier:
85
86 $WT = FooHandle->new_tie(&FOO_RDWR, 2);
87
88 The bottom line: now, almost any class can look and work exactly like
89 an IO::Handle and be used both with OO and non-OO file handle syntax.
90
92 The data structures
93 Consider this example code, using classes in this distribution:
94
95 use IO::Scalar;
96 use IO::WrapTie;
97
98 $WT = wraptie('IO::Scalar',\$s);
99 print $WT "Hello, ";
100 $WT->print("world!\n");
101
102 In it, the "wraptie" function creates a data structure as follows:
103
104 * $WT is a blessed reference to a tied filehandle
105 $WT glob; that glob is tied to the "Slave" object.
106 | * You would do all your i/o with $WT directly.
107 |
108 |
109 | ,---isa--> IO::WrapTie::Master >--isa--> IO::Handle
110 V /
111 .-------------.
112 | |
113 | | * Perl i/o operators work on the tied object,
114 | "Master" | invoking the C<TIEHANDLE> methods.
115 | | * Method invocations are delegated to the tied
116 | | slave.
117 `-------------'
118 |
119 tied(*$WT) | .---isa--> IO::WrapTie::Slave
120 V /
121 .-------------.
122 | |
123 | "Slave" | * Instance of FileHandle-like class which doesn't
124 | | actually use file descriptors, like IO::Scalar.
125 | IO::Scalar | * The slave can be any kind of object.
126 | | * Must implement the C<TIEHANDLE> interface.
127 `-------------'
128
129 NOTE: just as an IO::Handle is really just a blessed reference to a
130 traditional file handle glob. So also, an "IO::WrapTie::Master" is
131 really just a blessed reference to a file handle glob which has been
132 tied to some "slave" class.
133
134 How "wraptie" works
135 1. The call to function "wraptie(SLAVECLASS, TIEARGS...)" is passed
136 onto IO::WrapTie::Master::new(). Note that class
137 "IO::WrapTie::Master" is a subclass of IO::Handle.
138
139 2. The "IO::WrapTie::Master->new" method creates a new IO::Handle
140 object, re-blessed into class "IO::WrapTie::Master". This object is
141 the master, which will be returned from the constructor. At the
142 same time...
143
144 3. The "new" method also creates the slave: this is an instance of
145 "SLAVECLASS" which is created by tying the master's IO::Handle to
146 "SLAVECLASS" via "tie". This call to "tie" creates the slave in
147 the following manner:
148
149 4. Class "SLAVECLASS" is sent the message "TIEHANDLE"; it will usually
150 delegate this to "SLAVECLASS->new(TIEARGS)", resulting in a new
151 instance of "SLAVECLASS" being created and returned.
152
153 5. Once both master and slave have been created, the master is
154 returned to the caller.
155
156 How I/O operators work (on the master)
157 Consider using an i/o operator on the master:
158
159 print $WT "Hello, world!\n";
160
161 Since the master $WT is really a "blessed" reference to a glob, the
162 normal Perl I/O operators like "print" may be used on it. They will
163 just operate on the symbol part of the glob.
164
165 Since the glob is tied to the slave, the slave's "PRINT" method (part
166 of the "TIEHANDLE" interface) will be automatically invoked.
167
168 If the slave is an IO::Scalar, that means "PRINT" in IO::Scalar will be
169 invoked, and that method happens to delegate to the "print" method of
170 the same class. So the real work is ultimately done by "print" in
171 IO::Scalar.
172
173 How methods work (on the master)
174 Consider using a method on the master:
175
176 $WT->print("Hello, world!\n");
177
178 Since the master $WT is blessed into the class "IO::WrapTie::Master",
179 Perl first attempts to find a "print" method there. Failing that, Perl
180 next attempts to find a "print" method in the super class, IO::Handle.
181 It just so happens that there is such a method; that method merely
182 invokes the "print" I/O operator on the self object... and for that,
183 see above!
184
185 But let's suppose we're dealing with a method which isn't part of
186 IO::Handle... for example:
187
188 my $sref = $WT->sref;
189
190 In this case, the intuitive behavior is to have the master delegate the
191 method invocation to the slave (now do you see where the designations
192 come from?). This is indeed what happens: "IO::WrapTie::Master"
193 contains an "AUTOLOAD" method which performs the delegation.
194
195 So: when "sref" can't be found in IO::Handle, the "AUTOLOAD" method of
196 "IO::WrapTie::Master" is invoked, and the standard behavior of
197 delegating the method to the underlying slave (here, an IO::Scalar) is
198 done.
199
200 Sometimes, to get this to work properly, you may need to create a
201 subclass of "IO::WrapTie::Master" which is an effective master for your
202 class, and do the delegation there.
203
205 Why not simply use the object's OO interface?
206
207 Because that means forsaking the use of named operators like "print",
208 and you may need to pass the object to a subroutine which will attempt
209 to use those operators:
210
211 $O = FooHandle->new(&FOO_RDWR, 2);
212 $O->print("Hello, world\n"); ### OO syntax is okay, BUT....
213
214 sub nope { print $_[0] "Nope!\n" }
215 X nope($O); ### ERROR!!! (not a glob ref)
216
217 Why not simply use tie()?
218 Because (1) you have to use "tied" to invoke methods in the
219 object's public interface (yuck), and (2) you may need to pass the tied
220 symbol to another subroutine which will attempt to treat it in an OO-
221 way... and that will break it:
222
223 tie *T, 'FooHandle', &FOO_RDWR, 2;
224 print T "Hello, world\n"; ### Operator is okay, BUT...
225
226 tied(*T)->other_stuff; ### yuck! AND...
227
228 sub nope { shift->print("Nope!\n") }
229 X nope(\*T); ### ERROR!!! (method "print" on unblessed ref)
230
231 Why a master and slave?
232
233 Why not simply write C<FooHandle> to inherit from L<IO::Handle?>
234 I tried this, with an implementation similar to that of L<IO::Socket>.
235 The problem is that I<the whole point is to use this with objects
236 that don't have an underlying file/socket descriptor.>.
237 Subclassing L<IO::Handle> will work fine for the OO stuff, and fine with
238 named operators I<if> you C<tie>... but if you just attempt to say:
239
240 $IO = FooHandle->new(&FOO_RDWR, 2);
241 print $IO "Hello!\n";
242
243 you get a warning from Perl like:
244
245 Filehandle GEN001 never opened
246
247 because it's trying to do system-level I/O on an (unopened) file
248 descriptor. To avoid this, you apparently have to "tie" the handle...
249 which brings us right back to where we started! At least the
250 IO::WrapTie mixin lets us say:
251
252 $IO = FooHandle->new_tie(&FOO_RDWR, 2);
253 print $IO "Hello!\n";
254
255 and so is not too bad. ":-)"
256
258 Remember: this stuff is for doing FileHandle-like I/O on things without
259 underlying file descriptors. If you have an underlying file
260 descriptor, you're better off just inheriting from IO::Handle.
261
262 Be aware that new_tie() always returns an instance of a kind of
263 IO::WrapTie::Master... it does not return an instance of the I/O class
264 you're tying to!
265
266 Invoking some methods on the master object causes "AUTOLOAD" to
267 delegate them to the slave object... so it looks like you're
268 manipulating a "FooHandle" object directly, but you're not.
269
270 I have not explored all the ramifications of this use of "tie". Here
271 there be dragons.
272
274 Eryq (eryq@zeegee.com). President, ZeeGee Software Inc
275 (http://www.zeegee.com).
276
278 Dianne Skoll (dfs@roaringpenguin.com).
279
281 Copyright (c) 1997 Erik (Eryq) Dorfman, ZeeGee Software, Inc. All
282 rights reserved.
283
284 This program is free software; you can redistribute it and/or modify it
285 under the same terms as Perl itself.
286
287
288
289perl v5.38.0 2023-07-20 IO::WrapTie(3)