Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Identify the package a subroutine is being called from

by Herkum (Parson)
on Jun 06, 2008 at 16:56 UTC ( [id://690700]=perlquestion: print w/replies, xml ) Need Help??

Herkum has asked for the wisdom of the Perl Monks concerning the following question:

I have a base module that I want to auto-generate information depending on the package that is originating the call. However, I cannot think of anything that provides that context. Here is my non-working example:
#!/usr/bin/perl use strict; use warnings; print "Calling: " . Calling::package_name() . "\n"; # Displays 'main' +and needs to be 'Calling' print "Calling2: " . Calling2::package_name() . "\n"; # Displays 'main +' and needs to be 'Calling2' package Test; sub package_name { return (caller)[0] } # What to replace caller with? package Calling; use base 'Test'; package Calling2; use base 'Test';

Suggestions?

Update: kyle pointed out, that it complains about an undefined subroutine. It appears that you cannot inherit a subroutine and try to call it without passing either a blessed reference or the package name to it.

Replies are listed 'Best First'.
Re: Identify the package a subroutine is being called from
by pc88mxer (Vicar) on Jun 06, 2008 at 17:04 UTC
    You can get more information by calling caller in list context:
    package Test: sub package_name { my @c = caller(0); $c[3]; }
    Although, the way you have set things up, this will return Test::package_name for both Calling->package_name and Calling2->package_name. Technically this is correct so you could add information about $_[0] in the result.
    sub package_name { my @c = caller(0); "$c[3] (with self = $_[0])" }
      You can get more information by calling caller in list context

      Actually (caller)[0] does call it in list context. The number of arguments to caller matters, though:

      $ perl -wle 'sub foo { my @l = caller(); return scalar @l }; print foo +()' 3 $ perl -wle 'sub foo { my @l = caller(0); return scalar @l }; print fo +o()' 10
        You're right. How may we invoke caller? Let us count the ways:
        $package = caller; @info = caller; # -> ($package, $file, $line) $package = caller($i); @extra_info = caller($i); # -> ($pack, $file, $line, $sub, $hasargs, ...)
Re: Identify the package a subroutine is being called from
by moritz (Cardinal) on Jun 06, 2008 at 17:05 UTC
    If you need that kind of information, you have to use the Package->subroutine() syntax (at least I think so). Then the package name is passed as the first argument, just like the object is in method calls.

      Well, I am adding code onto an existing module, and I cannot guarantee thats how they call the subroutine. It is driving me nuts because of it too! Otherwise that would have been the easy way to fix it.

Re: Identify the package a subroutine is being called from
by kyle (Abbot) on Jun 06, 2008 at 17:31 UTC

    The code snippet you posted does not execute for me.

    Undefined subroutine &Calling::package_name called

    It runs if I change Blah::package_name() to Blah->package_name(). The former will look for package_name only in the package you specify. The latter will look for it in the inheritance tree in the way you're talking about.

    That being the case, moritz is correct. The package name you're looking for is the first thing in @_. If it's not there, then maybe you want __PACKAGE__.

    If there's something I'm missing, please post some working code that shows the problem.

      No, you are correct, I made a bad assumption evidently. You HAVE to call the subroutine with a package name( or blessed reference) or it will blow up(at least when you are using inheritance).

      It was not the answer I expected, but it is an answer.

Re: Identify the package a subroutine is being called from
by jettero (Monsignor) on Jun 06, 2008 at 17:10 UTC
    Corollary, anyone have any idea how to get the calling object instance? I've always wanted that in perl. I don't think you can get it. It's called previous_object() in pike/lpc...

    -Paul

      The debugger certain can get the calling arguments, even if @_ has been modified (i.e. shifted).

      Here's a solution using Devel::StackTrace:

      use Devel::StackTrace; sub calling_object { my $t = Devel::StackTrace->new; my $f; $f = $t->next_frame for (1..4); ($f->args)[0] } sub e { my $x = shift; print "x = $x\n"; d('humma'); } sub d { print "I was called by object ", calling_object(), "\n"; } e('a', 'b', 'c');
        Holy crap. That's exactly what I wanted. I should have asked years ago.

        -Paul

      This may work, depending on what happened to @_:

      package DB; sub get_calling_object { my @foo = caller(2); return $DB::args[0] }

      Update: This needs the package declaration.

        I do not understand what $DB::args[0] is, but I suspect this is intended to return the package name of the caller, not the instance of the caller object.

        -Paul

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://690700]
Approved by pc88mxer
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (2)
As of 2024-04-20 03:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found