What is a "handle" in Perl?

Viewed 109

Wondering what the handle is in Perl.

I can see file handle, directory handle..etc but want to know the meaning of the handle in Perl.

For example, in IO::Pipe, I can see below explain. And want to make clear the meaning of "becomes a handle"?

reader ([ARGS])

The object is re-blessed into a sub-class of IO::Handle, 
and becomes a handle at the reading end of the pipe. If 
ARGS are given then fork is called and ARGS are passed 
to exec.

Also could you please explain the meaning of bless?

3 Answers

A handle is an way to get to something without actually being that thing. A handle has an interface to interact with something managed by system (or something else).

Start with the idea of a scalar. Defining a simple scalar stores a value and that value is actually in the memory of your program. In very simplistic terms, you manage that resource directly and wholly within your program. You don't need to ask the system to do increment the variable for you:

 my $n = 5; 
 $n++;

Talking to the outside world

A handle represents a connection to something managed by something else, typically through "system calls".

A file handle is your connection to a file (so, managed by the filesystem or OS) but is not the file itself. With that filehandle, you can can read from or write to the file, there is code behind all that to talk to the system to do the actual work.

 open my $filehandle, '<', $filename or die "$!";

Since you are not managing the actual work and since you depend on the system to do the work, you check the $! system error variable to check that the system was able to do what you wanted. If it couldn't, it tells you how it ran into a problem (although the error may not be very specific).

A directory handle is a way to get a list of the things inside a directory, but is not the directory itself. To get that, you have to ask the system to do things for you. And so on.

Perl is wonderful though

But, in Perl, you can make a handle to anything you like (and I write a lot about this in either Effective Perl Programming and Mastering Perl. You can use the interface for a handle even if you wholly control the thing and don't need to ask the system to do something on your behalf.

For example, you can use the filehandle interface on a string:

 open my $string_filehandle, '>', \my $string;
 print {$string_filehandle} "This goes to the string";

To your code as you read it, it looks like the thing is a file (socket, whatever) because the main use of the handle interface. This is quite handy when your are handcuffed to using a filehandle because someone else wrote some code you can't change. This function is designed to only send $message to some output handle:

sub print_to_file_only {
    my( $filehandle, $message ) = @_;
    print {$filehandle} $message;
    }

But sometime you don't want that message to go to the terminal, file, socket, or whatever. You want to see it in my program. You can capture the message in your $string_filehandle because it uses the same handle interface even though it's not a static resource.

print_to_file_only( $string_filehandle );

Now you'll see the message show up in $string, and you can do whatever you like with it.

There are many more tricks like this, and I'm tempted to talk about all of them. But, this should be a good start.

This can be a very broad topic and I'll try to stay with the crux of the question, captured in a line quoted from IO::Pipe docs which needs explaining

The object is re-blessed into a sub-class of IO::Handle, and becomes a handle at the reading end of the pipe.

A "handle" in Perl is a construct built around some resource, out in the OS or in our program, which allows us to manage that resource. A filehandle, for instance, may facilitate access to a file, via libraries and OS facilities, and is more than a plain file descriptor

use warnings;
use strict;
use feature 'say';

my $file = shift // die "Usage: $0 file\n";

open my $fh, '<', $file or die "Can't open $file: $!";
say fileno $fh;     # file descriptor, a small integer, normally >= 3
say $fh->fileno;    # can use handle as object of IO::Handle or IO::File
print while <$fh>;  # use it to access data at/via the resource
close $fh;

The opened file got a file descriptor in the OS, a small integer, the first one available.† But we get the "filehandle" $fh associated with the opened file, which is far nicer to work with and with which various tools can be used. (The fileno was used to get the fd from it.)

In newer Perls (since v5.14.0) a (file)handle can in fact be treated as an object of IO::Handle or IO::File, as these classes get loaded on demand once a method call from them is used on the variable with the handle (if the call can't be resolved otherwise).‡

This brings us to the second question, of "re-bless"-ing.

When a reference is bless-ed into a package it becomes an object of (the class supposedly defined in) that package. A sub this is done in is thus a constructor and such "blessed" reference is returned to the caller. That is an "instance" of the class in the caller, an object.

The object's internal structure has fields saying what package it's from so it gets treated accordingly, one can call methods defined in the package on it, etc. This is a bit simplified, see perlootut and perlobj for starters.

The quote from the docs comes from the reader or writer methods in IO::Pipe class. Once they are called on an object of that class it becomes beneficial for the object to have facilities from IO::Handle, so it is "made" into an object of that class. (Not of IO::File class since a pipe isn't seekable while IO::File inherits from IO::Seekable as well.)

Since bless is a crucial and telling part of the process peopple often simply say that it's "blessed" (or "re-blessed" here since it was already an object of another class), but as you can see from the linked sources there is a bit more to do.

As a final comment, note that a "(file)handle" can be opened to things entirely other than an OS resource like a file or socket or such. For example, it can be "tied" (see perltie, Tie::Handle); or, opened to a scalar ("in-memory file").§


† If STDIN/STDOUT/STDERR (fd's 0,1,2) aren't closed and this is the first thing opened, it gets 3

‡ The IO::File inherits from IO::Handle and IO::Seekable, adding only a few methods. Most classes that represent handles, like IO::Pipe or IO::Select, inherit from IO::Handle. So its docs, first, provide a feel for what is available for a handle, so what a "handle" is.

§ This isn't a full filehandle though; try fileno on it (-1). But it behaves well enough to be useful. One example: I use it in forked processes to accumulate prints in a child in a string, which is in the end sent back to the parent. That way they can be logged/printed coherently, and in some order.

# in a child
my $stdout;
open my $fh_stdout, '>', \$stdout  or croak "Can't open var for write: $!";
my $fh_STDOUT = select $fh_stdout;  # set as default, save old (STDOUT)

say "goes to string";  # winds up in $stdout (sent to parent in the end)

select $fh_STDOUT;  # cna switch back (normally not needed in child)

This can be done in other ways of course (append messages to a string, for example) but this way we can print normally once the handle is select-ed as default (and can use existing subs/libraries which may just print, not caring where they run, etc).

Most languages create variables and objects in very different ways. In Perl, they are very similar.

Perl allows most types of variables to be marked as an object by the bless functionality.

This confer additional powers to the variable to call methods in the class. Perl will search that class for a method of that name. If you fail to supply the second argument to bless, it will use the current package or class to search.

In their IO::Pipe example, you call IO::Pipe's new() method to obtain a blessed object. To them make use, they fork() and the parent converts ("re-blessed") $pipe to a reader subclass of IO::Pipe with methods calls that work as a reader. The child process converts their $pipe to a write. Now they may communicate from child to parent via the pipe.

Related