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
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |