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

Hello all!

I loaded one module into my package like this:

In MyClass.pm: { package MyClass; use mymodule; # call some function from mymodule }
and afterwards I load the same module into main package:
In myapp.pl: use mymodule; # call some function from mymodule
The problem is that I can normally call functions from mymodule within MyClass but calling the same functions within main throws an error about functions not being defined. I don't have any package declarations in mymodule.pm; it's just a file with a lot of functions.

I resolved this by putting use mymodule in MyClass outside of package definition and brackets and now everything works fine, but I still don't know why the previous code failed to work.

Can it be because of Class::Contract? I use it to construct a class in MyClass. Does it somehow obscure loaded functions in MyClass so that no other packages can use it? (I know it sounds funny and probably is wrong, but that's the only reason I can think of.)

Any suggestions/descriptions/pointers to docs/slaps are appreciated.

Update: sample test code similar to the original and it doesn't work:

test_loading.pl:

#!/usr/bin/perl -w use strict; use warnings; { package MyClass; use Class::Contract; use test_func; contract { attr 'test'; ctor 'new'; impl { ${self->test} = test_me('within class'); }; }; }; package main; use test_func; test_me('in main');

test_func.pm

sub test_me { my $txt = shift; print "Exec of test_me with: $txt\n"; return $txt; } 1;

It throws an error:

Undefined subroutine &main::test_me called at test_loading.pl line 25

It works fine when I remove use test_func from MyClass and call test_me() like main::test_me() in class ctor.

Replies are listed 'Best First'.
Re: Loading a module into many packages
by diotalevi (Canon) on Oct 26, 2006 at 17:14 UTC

    I don't have any package declarations in mymodule.pm; it's just a file with a lot of functions.
    That's your problem. Use declaration package mymodule; in it and use Exporter to export your functions.

    Also note that Class::Contract isn't meant for production according to Categorized Damian Modules.

    ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

      That's your problem. Use declaration package mymodule; in it and use Exporter to export your functions.

      Indeed, that is my problem because I inherited a large Perl code base written exactly in that way: a lot of files with a lot of perl functions. No packages, no classes. I try to put some common modules into that mess, but I really think I should remove all that crap and write the stuff from the very beginning.

      I know about Class::Contract and Damian's classification. I use Class::Contract for merely non-serious software. It has nice and clean interface I like. Actually my next question on SoPW was planned to be: why not use Class::Contract in production, but I think I'm going to explore Object::InsideOut and forget about C::C.

        Here's what happens when you use() your mymodule.pm the first time. The file mymodule.pm is located and compiled. You didn't declare a new package so everything is loaded into your current package. Then mymodule->import() is attempted. That doesn't exist so nothing happens. Your next module use()'s mymodule. Now only mymodule->import() is called. This is how you tell perl that this file has things to export. When you don't use packages and Exporter then perl will assume it's already compiled the thing and not bother trying again.

        Here are some workarounds:

        • use do() instead and name the file specifically. That'll run regardless of whether perl has seen it before or not.
        • Remove the mymodule.pm entry in %INC in a BEGIN block just prior to use()ing it. BEGIN { delete $INC{'mymodule.pm'} }
        • Add the code I said you were missing. It can't be helped, really.

          ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

Re: Loading a module into many packages
by mreece (Friar) on Oct 26, 2006 at 16:31 UTC
    you can solve this two ways.

    1. do "test_func.pm"; instead of use test_func;

    2. change test_func.pm to a proper package that exports its functions:

    package test_func; use base qw(Exporter); our @EXPORT = qw(test_me); sub test_me { my $txt = shift; print "Exec of test_me with: $txt\n"; return $txt; } 1;
Re: Loading a module into many packages
by Fendaria (Beadle) on Oct 26, 2006 at 15:09 UTC
    I'd start with a minimal test case. Does 'Hello world' run?

    #!/usr/bin/perl use strict; use warnings; use mymodule; print "Hello World\n";

    Does your module load?

    Then, can you call a sub in your module?

    Slowly build yourself back up to your main program adding in more code to see what is going on.

    I know it sounds simplistic but this has helped me a ton of times.

    Fendaria
      See an update. mymodule loads ok. I use it in many other places without problems.
        Is that really all/exactly the code in your module? If this is the case, your module isn't in a package and is just raw perl code. This perl code is getting inserted into your MyClass package which is probably not what you want. I removed the other class and this still generates the error, which leads me to believe this is your problem.

        { package MyClass; use test_func; test_me('in class'); };

        This is a problem of package scoping test_func.pm should look something like this...

        package test_func; sub test_me { #..... } 1;

        You can then call the test_me as &test_func::test_me from main

        I would highly recommend taking a look at the package Exporter.

        The perl docs on packages and modules would also be very helpful. perlmod

        Fendaria