Home > Mobile >  In perl is \*STDIN the same as STDIN?
In perl is \*STDIN the same as STDIN?

Time:12-05

I'm the author of Pythonizer and I'm trying to translate the code of CGI.pm from the standard perl library to Python. I came across this code in read_from_client:

read(\*STDIN, $$buff, $len, $offset)

Is \*STDIN the same thing as just STDIN? I'm not understanding why they are using it this way. Thanks for your help!

The module also references \*main::STDIN - is this the same as STDIN too (I would translate plain STDIN to sys.stdin in python)? Code:

foreach my $fh (
    \*main::STDOUT,
    \*main::STDIN,
    \*main::STDERR,
) { ... }

CodePudding user response:

Instead of translating CGI.pm line for line, I'll recommend you understand the interface then do whatever Python would do for that. Or, better yet, just forget it exists. It often seems like a translation will be a drop-in replacement, but since the libraries and structures you'll use in the new language are different enough that you are just going to make new bugs. Since you are going to make new bugs anyway, you might as well do something smarter.

But, I know nothing about your situation, so let's get to the literal question.

You're looking at:

# Read data from a file handle
sub read_from_client {
    my($self, $buff, $len, $offset) = @_;
    local $^W=0;                # prevent a warning
    return $MOD_PERL
        ? $self->r->read($$buff, $len, $offset)
        : read(\*STDIN, $$buff, $len, $offset);
}

Instead of worrying about the Perl code, just do whatever you need to do in Python to satisfy the interface. Given a buffer and a length, get some more data from the filehandle. Since you are not handling mod_perl (I'm guessing, because how would you?), you can ignore most stuff there.


The \*main::STDIN and \*STDIN are references to a typeglob, which is a way to track all the Perl variables with the same name (scalar, array, hash, subroutine, filehandle, and a few others). The STDIN identifier is a special case variable that is main by default, so adding the package main:: in front is probably merely developer comfort.

When you use those reference in a place that wants to work on a filehandle, the filehandle portion of the type glob is used. It's just a way to pass the identifier STDIN and have something else use it as a filehandle.

You see this as a way to pass around the named, standard file handles.

The read takes a filehandle (or reference to typeglob) as its first argument.

In python, you'd do something like sys.stdin.read(...).

CodePudding user response:

The following can usually be used a file handle:

  • An IO object (*STDIN{IO})
  • A glob containing an IO object (*STDIN)
  • A reference to a glob containing an IO object (\*STDIN)
  • The name of a glob containing an IO object ("STDIN")

The builtin operators that expect a file handle allow you to omit the * when providing a glob. For example, read( FH, ... ) means read( *FH, ... ).

The builtin functions that expect a file handle should accept all of these. So you could any of the following:

  • read( *STDIN{IO}, ... )
  • read( STDIN, ... )
  • read( *STDIN, ... )
  • read( \*STDIN, ... )
  • read( "STDIN", ... ).

They will have the same effect.


Third-party libraries probably accept the globs and reference to globs, and they should also expect IO objects. I expect the least support for the providing the name as a string. Your mileage may vary.

You can't go wrong with a reference to a glob (\*FH) since that's what open( my $fh, ... ) produces.

  • Related