Note: If the only reason you want to have a custom module is to keep your program short and move common functions to a separate file or out of view, so your program doesn't appear cluttered, then there is another solution you may consider. This is sometimes discouraged by Perl programmers, because it is not the "proper way" to include a module, but you could do this:

Create a file named "myModule.pl" and you shall paste the following code in it:


print "\nHello, myModule.pl is running now! Called by $PROGRAM_NAME "; sub trim { my $string = shift; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } # Left trim function to remove leading whitespace sub ltrim { my $string = shift; $string =~ s/^\s+//; return $string; } # Right trim function to remove trailing whitespace sub rtrim { my $string = shift; $string =~ s/\s+$//; return $string; } # This is for demonstration purpose only: my $PI = 3.141; sub value_of_pi { return $PI; } non_existent_sub();

Now, you'll create another file called "MainProgram.pl" and paste the following in it:


#!/home/myhomedrive/opt/perl/bin/perl use strict; use warnings; my $PROGRAM_NAME = "Test"; # The following line reads the entire myModule.pl file and executes it + using eval(): @ARGV = "myModule.pl"; eval(join('',<>)); my $string = " ll "; $string = trim( $string ); print "\n|$string|\n"; print "\n", value_of_pi();

This is an easy way to include a big module without a lot of hocus pocus.

Here are a few important things to note:

1. When implemented this way, your module may or may not start with the shebang. It's not required.

2. Your module now does not have to end with 1; because it's technically no longer a module anymore. It's just a piece of text that you read and eval it. So, you don't have to write "package myModule" in your module, because it's not a module.

3. Anytime you write some error in your perl code, the perl interpreter will tell you if warnings and strict is on. However, if you put the perl code in quotation marks and eval it, then it won't alert you of any errors! So, you may notice that I put a call to a non_existent_sub(); at the end of your module, and perl won't scream at you that it found an error! In fact, you could expand your module and write grave errors in it, and perl will never alert you since it's being imported using the eval command. So, this is a pretty big disadvantage of using eval. Now, of course, you could test your module separately, but I'm just letting you know this is the catch. lol

Edit: 3b. The other "catch" is that this strategy poses a vulnerability. Let's say that your computer gets infected with a virus that is specifically designed to attack your program. It will modify your MyModule.pl file, and you won't even notice that foreign code is now running on your PC. But for this to happen, some outside entity must get write access to your module file. So, it is a bit of a security risk. You wouldn't want a perl script running in a bank server to employ tricks like this. But if it's only for your personal use and you're not working on some top secret, then it's okay, I think. :D

3c. The other potential vulnerability is if this module was stored in a text file on a server or just in a pl file but it has no shebang line in it and you forget to set the execute bit, then guess what. Someone who types in the exact web address of this module is going to see the source code of your module. And that's usually a big no-no. If you let anybody see your source code, it may help them exploit vulnerabilities that otherwise they might never find.

4. A neat idea is you can put some program code in your module. I just put a print statement in it, and you'll see that as soon as you eval it, it gets printed. So, your module could call subs such as Init() or whatever you want to do to do some things without cluttering your main program. This can be nice.

5. Another gotcha is the value of $PI which I declare using my in the module. Now, even I myself don't understand why, but the $PI variable is not accessible from your main program. It can only be accessed through the function called value_of_pi() which if you call, then you get the value of $PI. But otherwise, you can't just access it. This is both an advantage and disadvantage. It's an advantage because whatever variables you declare in your module are going to be hidden or masked so the main program won't see them. But it's also a disadvantage, because sometimes maybe you want to access the value, and you can't. Well, then you would put the declaration "my ..." in your main program, and now you can access it anywhere in the program! See, the variable $PROGRAM_NAME? I created that variable in the main program, and it is accessible from the module. But if you declare a variable in the module, it's not accessible from the main program. Don't ask me why. I don't know. Lol

6. I chose a shortcut for reading the entire module and executing it with eval. This shortcut is done by erasing the program's arguments and replacing them with a single file name you want to read. And then using <> to read the entire file. The problem is if your program relies on arguments or expects the user to type in some arguments, then you're screwed. So, then you would read the file and eval its contents by some other means. For example, you could read the file using sysopen() sysread() and then close() and then eval() whatever you just read. That would be another way to read the file. But doing @ARGV = ... thing is so much more compact. It is a bit cryptic, but hey, everything in perl is that way. lol You should probably write a comment above that line explaining what it does, because you may forget it a few years from now.

7. I erased the dollar sign from sub trim($) because it isn't necessary. In fact, it is confusing. In perl, when you pass arguments, the arguments are treated as a list or array. So, if your sub expects 3 strings, then you can pass an array containing 3 strings, and your sub will see it as three individual arguments. But if you want your sub to see the arguments as one string followed by an array, then that's when you should use the ($@) or whatever. But otherwise it has no purpose. In fact, I like to avoid this stuff altogether, because I heard that the way this is interpreted in newer perl versions has been changed, in other words it might break compatibility of your code. But that's not 100% true. Somebody please correct me. :P


In reply to Re: Trouble usig a subroutine from a custom module by harangzsolt33
in thread Trouble usig a subroutine from a custom module by fritz1968

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.