how to call a function using variable

A

Amaninder

Hi everyone

There is a class called Message.pm which has a function
sub INTEGER() { 0x02 }

and i have a variable called $function which has value 'INTEGER'
$function = 'INTEGER'

I want to get the 0x02 doing something like this
$a = Net::SNMP::Message::$function();
But its not working. Can someone suggest me how to use the function
INTEGER() of someClass if i have 'INTEGER' as string in $function .

I tried this and it works
$a = Net::SNMP::Message::INTEGER();

Thanks in advance.

Regards
Amaninder Saini
 
I

it_says_BALLS_on_your forehead

Amaninder said:
Hi everyone

There is a class called Message.pm which has a function
sub INTEGER() { 0x02 }

and i have a variable called $function which has value 'INTEGER'
$function = 'INTEGER'

I want to get the 0x02 doing something like this
$a = Net::SNMP::Message::$function();
But its not working. Can someone suggest me how to use the function
INTEGER() of someClass if i have 'INTEGER' as string in $function .

I tried this and it works
$a = Net::SNMP::Message::INTEGER();

use strict;
use warnings;

# print foo();

my $ref = \&foo;

print $ref->();

sub foo {
return "hi\n";
}
 
B

Brian McCauley

Amaninder said:
Hi everyone

There is a class called Message.pm which has a function

Are you sure? Are you sure it's not the class Net::SNMP::Message in
the file Net/SNMP/Message.pm. (Being precise can be important in
programming).
sub INTEGER() { 0x02 }

and i have a variable called $function which has value 'INTEGER'
$function = 'INTEGER'

I want to get the 0x02 doing something like this
$a = Net::SNMP::Message::$function();
But its not working. Can someone suggest me how to use the function
INTEGER() of someClass if i have 'INTEGER' as string in $function .

Perhaps the simplest is to use a symbolic method reference...

$a = Net::SNMP::Message->$function();

Note that because this is a class method call the first argument passed
Net::SNMP::Message::INTEGER will be the string 'Net::SNMP::Message'.
This probably doesn't matter here.

Note more importantly that $function could be an arbitrary qualified
function name and this might be exploitable to break into your system
if $function comes from an untrusted source.

I prefer...
{
no strict 'refs';
$a ="Net::SNMP::Message::$function"->();
}

This is better because

1) It has a big red flag saying "I'm using symrefs"

2) It does not pass any unwanted arguments

3) It cannot be abused to call functions except in namespaces
starting Net::SNMP::Message:

Note: other people will probably tell you not to use a symbol table as
dispatch table but to write your own. There are often (usually) good
reasons to follow that advice, but this is possbily not one of those
occasions.
 
U

Uri Guttman

BM> I prefer...
BM> {
BM> no strict 'refs';
BM> $a ="Net::SNMP::Message::$function"->();
BM> }

BM> This is better because

BM> 1) It has a big red flag saying "I'm using symrefs"

BM> 2) It does not pass any unwanted arguments

BM> 3) It cannot be abused to call functions except in namespaces
BM> starting Net::SNMP::Message:

i think a dispatch table is even better. no symrefs at all. you can use
it with method or regular calls too. they are safer too as you can limit
what functions/methods can be called. who knows where the function name
has come from?

OP: search this group on google for many threads on how to create and
use dispatch tables.

BM> Note: other people will probably tell you not to use a symbol table as
BM> dispatch table but to write your own. There are often (usually) good
BM> reasons to follow that advice, but this is possbily not one of those
BM> occasions.

i would disagree. when you can avoid the symbol table it is always a
good thing IMO. symrefs are always more dangerous and trickier (the no
strict refs being needed) than hard code refs.

uri
 
R

Robert Sedlacek

Brian McCauley said:
I prefer...
{
no strict 'refs';
$a ="Net::SNMP::Message::$function"->();
}

This is better because

1) It has a big red flag saying "I'm using symrefs"

2) It does not pass any unwanted arguments

3) It cannot be abused to call functions except in namespaces
starting Net::SNMP::Message:

It's not exactly the same though. Your version wouldn't care for
inheritance. But there's also

my $res = Net::SNMP::Message->can( $function )->( @args );

By splitting this up, you'd also get an easy way of verifying that the
function really exists.
Note: other people will probably tell you not to use a symbol table as
dispatch table but to write your own. There are often (usually) good
reasons to follow that advice, but this is possbily not one of those
occasions.

Possibly. Care to elaborate why you think it's not? A dispatch table
has more advantages than just keeping things away from the symbol table.
It is a kind of defined interface, and it doesn't matter what closure
lies behind. This can come in handy compared to function or method
calls.


p
 
B

Brian McCauley

Robert said:
It's not exactly the same though. Your version wouldn't care for
inheritance.

Which is a good thing here. The OP's problem was one of calling
function not methods.
But there's also

my $res = Net::SNMP::Message->can( $function )->( @args );

Which (appart from possibly getting sidetracked by inheritance) is just
another way of keeping symrefs whilst removing the red flag.

And, of course, it does't restrict $function to the Net::SNMP::Message
namespace which could be a major security issue.

It also gives a really unhelpful error if $function is invalid.

Use of uninitialized value in subroutine entry at....
Can't use string ("") as a subroutine ref while "strict refs" in use
at...
By splitting this up, you'd also get an easy way of verifying that the
function really exists.

Not one that's any easier than
exists(&{"Net::SNMP::Message::$function"})

However this is probably unnecessary because unlike the can()->()
mechanism the explicit symref gives a sane error.

Undefined subroutine &Net::SNMP::Message::WIBBLE called at...
Possibly. Care to elaborate why you think it's not? A dispatch table
has more advantages than just keeping things away from the symbol table.
It is a kind of defined interface, and it doesn't matter what closure
lies behind. This can come in handy compared to function or method
calls.

In the OP's problem there's already a defined interface. At least as
far as I understand it the OP is a user of Net::SNMP::Message not its
author. Sure Net::SNMP::Message could expose a hash, or have some
other API, but that's not what this is about. If the interface is
presented as a symbol table, wrapping it in another API is a
duplication of effort.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,297
Messages
2,571,530
Members
48,251
Latest member
Amelia8778

Latest Threads

Top