Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Perl method calls be intercepted?

Tags:

perl

Can you intercept a method call in Perl, do something with the arguments, and then execute it?

like image 889
Geo Avatar asked Sep 01 '09 21:09

Geo


2 Answers

Yes, you can intercept Perl subroutine calls. I have an entire chapter about that sort of thing in Mastering Perl. Check out the Hook::LexWrap module, which lets you do it without going through all of the details. Perl's methods are just subroutines.

You can also create a subclass and override the method you want to catch. That's a slightly better way to do it because that's the way object-oriented programming wants you do to it. However, sometimes people write code that doesn't allow you to do this properly. There's more about that in Mastering Perl too.

like image 162
brian d foy Avatar answered Sep 28 '22 20:09

brian d foy


To describe briefly, Perl has the aptitude to modify symbol table. You call a subroutine (method) via symbol table of the package, to which the method belongs. If you modify the symbol table (and this is not considered very dirty), you can substitute most method calls with calling the other methods you specify. This demonstrates the approach:

# The subroutine we'll interrupt calls to
sub call_me
{
    print shift,"\n";
}

# Intercepting factory
sub aspectate
{
    my $callee = shift;
    my $value = shift;
    return sub { $callee->($value + shift); };
}
my $aspectated_call_me = aspectate \&call_me, 100;

# Rewrite symbol table of main package (lasts to the end of the block).
# Replace "main" with the name of the package (class) you're intercepting
local *main::call_me = $aspectated_call_me;

# Voila!  Prints 105!
call_me(5);

This also shows that, once someone takes reference of the subroutine and calls it via the reference, you can no longer influence such calls.

I am pretty sure there are frameworks to do aspectation in perl, but this, I hope, demonstrates the approach.

like image 20
P Shved Avatar answered Sep 28 '22 18:09

P Shved