7

I am facing compilation error while declaring array type argument in perl subroutine defination. My complete code is below:

use Data::Dumper;
use Win32;
use Win32::Service;
use strict;
use warnings;
my @Services = qw(NNMAction RpcEptMapper smstsmgr SNMPTRAP);
my $server   = 'nnmi.hclt.corp.hcl.in';
ServiceStatus($server , @Services);

sub ServiceStatus ($serverName,@serverServices)
{       my %statcodeHash = (     '1' => 'stopped',
                             '2' => 'start pending',
                             '3' => 'stop pending',
                             '4' => 'running',
                             '5' => 'continue pending',
                             '6' => 'pause pending',
                             '7' => 'paused'            );

  foreach my $serv (@serverServices)
  {     my %status;
     my $ret = Win32::Service::GetStatus($serverName , $serv , \%status);
     if ($ret)
     {       print "success \t$statcodeHash{$status{CurrentState}} \t$serv\n";
     }
     else
     {       print Win32::FormatMessage(Win32::GetLastError()), "\n";
     }
   }
 }   

COMPILATION ERROR

>perl -w perl_RemoteServiceStatus.pl
Prototype after '@' for main::ServiceStatus : $serverName,@serverServices at per
l_RemoteServiceStatus.pl line 21.
Illegal character in prototype for main::ServiceStatus : $serverName,@serverServ
ices at perl_RemoteServiceStatus.pl line 21.
main::ServiceStatus() called too early to check prototype at perl_RemoteServiceS
tatus.pl line 16.
Global symbol "@serverServices" requires explicit package name at perl_RemoteSer
viceStatus.pl line 31.
Global symbol "$serverName" requires explicit package name at perl_RemoteService
Status.pl line 33.
Execution of perl_RemoteServiceStatus.pl aborted due to compilation errors.

Kindly help me debugging ths code. I am sure it would be a piece of cake for some.

1
  • 3
    perl has no mechanism for declaring argument types. prototypes look like they do that at first glance, but in fact serve a completely different purpose; you should not use them. Commented Dec 20, 2012 at 10:13

4 Answers 4

10

It is really simple: Do not use prototypes if you do not know how they work. To get your code running, change the subroutine declaration from:

sub ServiceStatus ($serverName,@serverServices)
{ #...

to:

sub ServiceStatus {
    my ($serverName, @serverServices) = @_;

edit: If you need to pass more than one array/hash to a subroutine, or an array/hash should be passed-in before some other value(s), you have to pass it by reference:

sub complex_params {
    my ($array1, $scalar, $hash, $array2) = @_;

    # dereference
    my @a1 = @$array1;
    my @a2 = @$array2;
    my %h  = %$hash;

    #...
}

# reference
complex_params(\@some_array, $some_scalar, \%some_hash, \@other_array);
Sign up to request clarification or add additional context in comments.

1 Comment

Thanksyou Matthias ! It helped :) Will keep this thing in mind.
6

Perl prototypes are not for naming parameters, or even for giving types to them, they are for creating evaluation contexts. You need to modify the subroutines like this:

sub ServiceStatus ($@){
  my ($serverName,@serverServices) = @_;   
  # ...
}

or totally get rid of the prototype:

sub ServiceStatus {
  my ($serverName,@serverServices) = @_;   
  # ...
}

1 Comment

Excellent perreal. Got your message loud and clear :) Thanks
4
sub ServiceStatus
{
    my ($serverName,@serverServices) = @_; # Declare variables and populate from @_, the parameter list.
    ...

}

2 Comments

Thanks RobEarl for your valuable answer
This comment was helpful to me (in 2015) when having worked in PHP and JavaScript for over a year, and forgot about the @_ context with subs in Perl. Thanks
3

what are you doing?

First! Don't try to use prototypes:

sub ServiceStatus($@){

}

Let's see, what you want:

Passing array or hash to function is a very old trick:

sub ServiceStatus{
my ($firstArgument, $refToSecondArgumentWhichIsArray) = @_;

#return undef unless defined($firstArgument&&$refToSecondArgumentWhichIsArray);
...
}

How to use this?

ServiceStatus($serverName, \@serverServices);

And what to do with refs?

$refToArray->[0]; <- first element of array you pass
@{$refToArray}    <- array you pass to function

1 Comment

Thanks loldop for your valuable help. I got my mistake while declaring prototypes but unfortunately didnt got your clear message in last part.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.