开发者

Perl : function call in constructor?

I would like to ameliorate my perl script which does SNMP request on a cisco switch. But I don't really understand constructor and giving args to function in perl...

This is my script :

#!/usr/bin/perl
use strict;
use warnings;
use Net::SNMP;
package SnmpTable;

my ($session, $error);

sub new {
  my ($classe, $hostname, $oid, $community) = @_;
  my $this = {
    "hostname"      => $hostname,
    "oid"           => $oid,
    "community" => $community
  };
  bless($this, $classe);
  return $this;
}

sub connexion {
    my ($this) = @_;
    #print "Connexion SNMP...\n";
    ($session, $error) = Net::SNMP->session(
        -hostname  => $this->{hostname},
        -community => $this->{community},
        -version   => "1",
        -timeout   => 3,
    );
    request_error_connexion() if (!defined($session));
    #print "Connexion établie\n";
}

sub request_error_connexion {   
    my ($this) = @_;
    print "Erreur : connexion SNMP impossible vers $this->{hostname}\n";
    print "Erreur : $error\n";
    if ($error =~ /The argument "-community" is unknown/)
        {
                # protocol SNMP version 3 non pris en charge
                exit 3;  # code retour final = 3*256 = 768
        }
    else
    {
        exit 1; # code retour final = 1*256 = 256
    }
}

sub request_error {
        my ($this) = @_;
        #print "Erreur : pas de réponse SNMP depuis l'hôte $this->{hostname} avec l'oid $this->{oid}\n";
        printf "Erreur : %s\n",$session->error;
        if ($session->error =~ /No response from remote host/)
        {
                #host ok, mais community surement erronée ou host refuse le connexion
                $session->close;
                exit 2; # code retour final = 2*256 = 512
        }
        else
        {
                #table introuvable
                $session->close;
                exit 4; # code retour final = 4*256 = 1024
        }
}

sub requete {
    my ($this) = @_;
    my $result = $session->get_table( -baseoid => $this->{oid} );
    request_error() if (!defined($result));
    my %tab = ();

    foreach my $i (Net::SNMP::oid_lex_sort(keys %{$result})) {
        my $index = $i;
        $index =~ s/$this->{oid}.//;
        $tab{ $index } = $result->{$i};  
        #print $index."--".$result->{$i}."\n";
    }

    $session->close();
    return %tab;
}

1;

In my constructor, I would like to create the SNMP session (using Net::SNMP), and not have to do it in a function 'connexion()'. When I create the instance, connexion() called automatically.

Moreover, I want function 'requete()' with arg (OID).

So I could create开发者_开发问答 only one instance, and doing all my request with it.

With that script I must create instances as many informations I want.

Hope, it's comprehensible... Thanks.


In new, before return put this:

$this->connexion;

To the OID parameter part:

sub requete {
    my ($this, $oid) = @_;

    $oid = $this->{oid}
        unless defined $oid;

    my $result = $session->get_table( -baseoid => $oid );
    request_error() if (!defined($result));
    my %tab = ();

    foreach my $i (Net::SNMP::oid_lex_sort(keys %{$result})) {
        my $index = $i;
        $index =~ s/$this->{oid}.//;
        $tab{ $index } = $result->{$i};  
        #print $index."--".$result->{$i}."\n";
    }

    $session->close();
    return %tab;
}

This will accept OID as a parameter, it the OID is not given as a parameter it will use OID from constructor.


I'm not 100% sure what your question is, but here's a go at trying to answer:

  1. How do subroutine arguments work in Perl?
  2. How does a constructor work in Perl?

Answers:

How do subroutine arguments work?

Subroutines in Perl are a bit unusual. See perldoc perlsub for all the details.

The short version is that any call to a subroutine is passed a list of arguments. It is up to the called code to handle the list however it wants.

The argument list is stored in the special @_ array. The members of @_ are actually aliases of the values passed in (think in terms of pass by reference), so it is possible to modify a calling argument. To avoid any accidents, most subroutines copy the elements of @_ into local variables. When you see my ($foo, $bar) = @_;, it copies the first two members of @_ into $foo and $bar. Another common idiom is my $foo = shift;. This removes the first item from @_ and copies it into $foo.

How does a constructor work?

In Perl OO methods are just subroutines, and the constructor is no different.

When you call a method $foo->do_this() or MyCoolClass->new() the item on the left side of the -> operator is called the invocant. The invocant determines in what name-spaces (packages in perl terms) the method will be searched for. When the invocant is a string literal, it is taken to be name of the package or class to start the search in. When the invocant is a scalar, it must be an object. In either case the invocant is also passed in as the first argument to the method when it is found and called. So a class method (such as new()) will expect a string for its first argument, while an instance method will expect an object.

A constructor, typically new() is usually a class method that creates an instance of the class to which it belongs. So Foo->new() will create a new Foo object.

A perl object is any reference that has been associated with a package by the use of the bless function.

Let's look at your constructor and see how it works:

sub new {

  # Unpack @_ into local variables
  # Notice that the class name is the first argument.
  my ($classe, $hostname, $oid, $community) = @_;


  # Create a reference to a hash with the arguments associated 
  # to particular keys in the hash.
  my $this = {
    "hostname"      => $hostname,
    "oid"           => $oid,
    "community" => $community
  };

  # Associate the hash ref with the class
  bless($this, $classe);

  # $this is now an object.  You can make method calls on it here.


  return $this;
}

Since constructor is like any other method or subroutine in Perl, you can do anything you want to in it. It's generally considered a good idea to keep your subroutines as simple as possible, but there is no reason why you couldn't make a Net::SNMP object in your constructor. If you make one, you should probably store it for later use.

sub new {
  my ($classe, $hostname, $oid, $community) = @_;

  my $this = {
    "hostname"      => $hostname,
    "oid"           => $oid,
    "community"     => $community,
    "connexion"     => undef,
  };

  bless($this, $classe);

  # Store the connection for later.
  # You could also modify connexion so that it stores the connection for you.
  $this->{connexion} = $this->connexion;

  return $this;
}

All this code presupposes that we want to use classical Perl OOP methods. While these techniques work well, there is a huge amount of activity surrounding the Moose Perl OO framework. Moose simplifies writing solid, well encapsulated OO code in Perl.

I strongly suggest that you pick up a copy of a book like Modern Perl. It will give you an updated look at Perl's OO tools, an introduction to Moose, as well as demonstrate many simple techniques that will make your code much easier to maintain.

I hope this is useful.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜