Programming in PerlNET: First Steps
This chapter opens the gate into the exciting world of programming Perl within the .NET environment. We start our journey with simple program examples. You will learn how to compile and run PerlNET programs. The new statements that make Perl to the .NET Framework interaction easy to use are introduced. After discussing PerlNET program structure and the use of namespaces, we demonstrate how to incorporate the input and output .NET classes into our programs. Finally, we present the full example program, which involves user interaction and shows how to bring into use Perl-specific constructions inside the .NET environment.
Your First PerlNET Program
As a first step in PerlNET programming, we write a simple program to introduce you to the basics of the new language. Our program outputs a single line of text. Here is the code for the first sample.
# # Hello.pl # use namespace "System"; use PerlNET qw(AUTOCALL); Console->WriteLine("Hello from Perl!");
The above code is saved in the Hello folder for this chapter. Optionally, you can just type the program in your favorite editor. If you are using Visual Perl
see Appendix A), you can open the solution Hello.sln. If you are not using Visual Perl, just ignore the solution and project files.
It is commonly known that Perl is a script language and as such is processed by Perl interpreter. So, the first reaction ("Perl instinct") is to type the following line:
and to get a "Hello from Perl!" line as an output. If you decided to try it, you got the following probably familiar but unpleasant response:
can't locate namespace.pm in @INC (@INC contains: . . .) at Hello.pl line 4 BEGIN failed compilation aborted at Hello.pl line 4.
Well, this is the moment to remind ourselves that from now on we will use Perl language (or more precisely, its extended version, PerlNET) to target our programs to the .NET environment. Therefore, we should be able to map any Perl program into MSIL (Microsoft Intermediate Language) assembly, which in turn can be executed by the .NET CLR (Common Language Runtime).
The work of compiling and building an assembly is done by plc.exe (PerlNET compiler), which comes with the PerlNET distribution. Simply run the following command from your command prompt in the Hello directory:
As a result, Hello.exe will be created. Now, you can test your first PerlNET program by executing Hello.exe. You should get the following output:
Hello from Perl!
Congratulations! You've just written, built, and executed your first fully functional PerlNET program. Reward yourself with a cup of coffee, and let's move on to the program discussion.
The first two lines after the starter comment in our sample are pragmas. These are instructions that tell the Perl interpreter how to treat the code that follows the pragma. Usually, you define pragmas at the beginning (header) of your Perl program, and then you write the code. Let us look at the first pragma.
use namespace "System";
This pragma tells Perl to look up types in the System namespace.1 As a result, we can use the unqualified type Console throughout our program. This means that we can write Console whenever referring to the System.Console class. This class encapsulates a rich functionality of the input/output operations.
Now let us look more closely at the second pragma.
use PerlNET qw(AUTOCALL);
In short, this line allows us to use the standard Perl call-method syntax when invoking static methods (class methods) of .NET classes. If we do not import AUTOCALL, then we must use the call function of the PerlNET module (we discuss this module shortly), as follows:
PerlNET::call("System.Console.WriteLine", "Hello from Perl!");
The first argument to the call function is the static method name to call. Starting from the second argument, you should specify the arguments list that you pass to the static method. If you specified the System namespace with the use namespace pragma, then you may omit it and write just Console.WriteLine when specifying the static method to the call function:
PerlNET::call("Console.WriteLine","Hello from Perl!");
Combining the two pragmas described above allows us to easily access .NET classes.
Console->WriteLine("Hello from Perl!");
This statement calls the static method WriteLine of the Console class, which is located in the System namespace. The WriteLine method is passed a string to output as argument.
In the previous section, we introduced the PerlNET module. Throughout this book, we will make wide usage of this module by importing useful functions that help the Perl language tap into the .NET environment.
Whenever you decide to use one of the functions provided by the PerlNET module, you may choose from two forms of syntax:
or you may import the function from PerlNET and write as follows:
use PerlNET qw(call); . . . call("System.Console.WriteLine", "Hello");
In most cases, we prefer to use the second form of syntax in this bookimporting all the function from the PerlNET module at the header of our Perl file. If you should use several PerlNET module functions, then you may enumerate them in the single use statement instead of importing each separately:
use PerlNET qw(AUTOCALL call enum);
As we saw in the previous sections, plc.exe, the PerlNET compiler, is used to build our programs and create assemblies. During compilation, plc checks a Perl file for syntactic accuracy. However, this check does not verify the correct spelling of .NET type names or the correct number of arguments passed to .NET methods. This means that you may misspell some .NET class or type name, but the PerlNET compiler will not let you know about this and will create an assembly. As a result, you will be informed about the error only at run-time.
Consider the following code (HelloErr), where we intentionally misspelled Console and wrote Consol:
# # HelloErr.pl # use strict; use namespace "System"; use PerlNET qw(AUTOCALL); Consol->WriteLine("Hello, World.\n");
If we compile this program, we get no errors and HelloErr.exe is created. However, if we run HelloErr.exe, then the following error is displayed:
System.ApplicationException: Can't locate type Consol . . .
The PerlNET compiler creates the .NET assembly, but internally our code is still being interpreted by the Perl Runtime Interpreter component, which passes our commands to .NET. It serves as a mediator between PerlNET programs and the .NET environment. Therefore, if we write two statements, the first correct and the second with error, then the Perl interpreter will execute the first statement, and on the second, we will get an error message:
Console->WriteLine("Hello from Perl"); Consol->WriteLine("Hello, World.\n");
The output will be
Hello from Perl System.ApplicationException: Can't locate type Consol . . .
PerlNET programs, like any Core Perl scripts, should pass through extensive runtime testing before being released.