3 Tutorial - Perl and Java
7 Java and Perl have different strengths and complement each other well.
9 You can connect them at runtime with tools such as JPL, PJC, or
10 ActiveX. In theory, you can convert Perl to Java bytecode, and
15 Not actually a conversion.
17 At this stage, we are generating Java opcodes by walking Perl's syntax
18 tree. This is very different from converting Perl to Java. It's a lot
21 =head1 1.1 Perl and Java, Compared
23 Perl offers rich text processing features, high-level network APIs,
24 excellent database integration, and a centralized repository of
31 Regular expression engine is a powerful sub language that can perform
32 complex text manipulations and extract data.
36 Packages such as libwww-perl (LWP) and libnet are powerful, high-level
37 interfaces to network functionality.
41 The Perl DBI is an interface to SQL data sources.
45 CPAN provides a centralized, organized archive of reusable code.
49 Java has a powerful graphical API, has numerous embedded
50 implementations, excellent database integration, but no single
51 recognized repository of reusable code.
57 The Swing (JFC) toolkit is a powerful toolkit for developing user
58 interfaces. Java also boasts 2D and 3D graphics APIs.
62 Java comes in embedded flavors, such as:
68 Kaffe C<http://www.transvirtual.com/> - embedded implementations for
73 Waba C<http://www.wabasoft.com/> - a subset of Java for Windows CE and
78 It's embedded into web browsers (Netscape and MS Internet Explorer)
88 Java's JDBC is similar to Perl's DBI
92 Java has many different repositories of code. Efforts such as the
93 Giant Java Tree C<http://www.gjt.org/> attempt to create a unified
98 =head1 1.2 Opportunities to Combine Java and Perl
100 You have a Java program with a lot of data that needs to be parsed,
101 filed, briefed, debriefed, and numbered.
103 You want to build your GUI in Java, but let Perl do the heavy lifting.
105 You've adopted the "Java is a systems language, Perl is a scripting
106 language" paradigm, and it works for you.
108 You're not sure which regex implementation to use:
110 C<org.teeth.green.loony.raving.monster.regex.*;>
112 C<com.zeppelin.regex.*;>
114 You want the I<B<best of both worlds>>.
116 =head1 1.3 Important Differences between Java and Perl
122 C<perl> compiles and executes programs each time you run them (unless you
123 use the Perl compiler).
127 C<javac> compiles programs in advance, C<java> runs them in the Java
132 The Java interpreter supports method overloading (methods can have the
133 same name, but are differentiated on the basis of their argument
134 types). Overloaded methods generally perform the same function, but
135 methods with a shorter argument list often use defaults:
139 // Draw a circle in the center of the screen
140 int drawCircle(int radius);
142 // Draw a circle at specified coordinates
143 int drawCircle(int radius, int h, int k);
149 The Perl interpreter doesn't support method overloading. In JPL, when
150 we call Java from Perl, we need to use some tricks to specify the Java
151 method we want to invoke. We'll learn about this when we see JPL's
158 At the time this presentation was prepared, JPL did not work with Perl
159 for Win32. However, JPL is in the core Perl distribution, and there
160 are plans to make it work with Perl for Win32.
162 With that in mind, I'm presenting the JPL material first, because it
163 is of interest to both Win32 and Unix Perl people. The Win32-specific
164 stuff (alternatives to JPL) will come last. I won't be offended if the
165 Unix people leave when I move to this section of the tutorial, since
166 there is no Unix material in that section. I'm perfectly happy to take
167 questions between JPL and ActiveX sections.
169 A subset of JPL now works on Win32. You can embed Java in Perl, but
170 you cannot embed Perl in Java (yet).
172 =head1 2.1 JPL Overview
174 Let's look at an overview of JPL.
176 =head2 2.1.1 Calling Perl from Java
178 Well-supported by JPL, but it is a complicated process:
184 The JPL preprocessor parses the I<.jpl> file and generates C code
185 wrappers for Perl methods. It also generates Java and Perl source
190 The C compiler compiles the wrapper and links it to the
191 I<libPerlInterpreter.so> shared library, producing a shared library for
196 The Java compiler compiles the Java source file, which uses native
197 methods to load the wrapper.
201 The wrapper connects the Java code to the Perl code in the Perl source
206 Fortunately, a generic F<Makefile.PL> simplifies the process. This is a
207 Perl script that generates a I<Makefile> for you.
209 =head2 2.1.2 Calling Java from Perl
211 This works best when Perl is embedded within a Java program.
213 The JNI Perl module creates and loads a JVM. There is no precompiler,
214 nothing extra -- it's just a Perl module and extension.
216 B<A Problem, Though>. In theory, you can call Java from standalone
217 Perl programs, but this doesn't work because some implementations
218 of Java use a user-level threads package (green threads) that
219 override some functions in the C library. Perl is comfortable
220 using these functions, but Java is not happy using the standard C
223 So, with green threads, you can't reliably embed Java in a standalone
226 Many Java implementations now use native threads. JPL has been tested
227 on Solaris with JDK 1.1.x and native threads, but not on Linux.
231 Oddly enough, this is the only way it works on Win32.
233 On Unix, I've still had trouble, even with native threads. I might
234 need to recompile perl with -DREENTRANT, but I'm not sure.
237 =head1 2.2 Working with JPL
239 How to set up a JPL application, compile, and install it.
241 =head2 2.2.1 Setting up a Project
247 The I<install-jpl> script creates the I<setvars> script. Source the
248 output of I<setvars> into your shell when you want to develop or run
253 Create a directory with the name of your project, such as
254 I<Frotz>. (if you want to use the generic F<Makefile.PL>, you need a
255 separate directory for each JPL class you create).
259 Copy the generic F<Makefile.PL> into the project directory. The
260 I<jpl/Sample> directory in the Perl distribution includes the generic
265 Write a I<.jpl> program with the same name as the project (such as
270 =head2 2.2.2 Compiling and Installing a Project
272 Type C<make> to compile the application, and C<make install> to
273 install it. This installs the application in the I<jpl> directory you
274 created when you installed JPL.
276 B<Beware>. The default I<jpl> directory is the same as the
277 directory you install it I<from>. If you go with the default and
278 delete your Perl source, you'll delete your JPL installation!
280 Type C<java Frotz> (or the name you chose in step 2 of section 2.2.1)
283 =head2 2.2.3 What's in the jpl Directory?
289 B<libPerlInterpreter.so>: a shared library that loads the Perl
294 Compiled F<.class> files for JPL applications you have written.
298 Native code shared library wrappers for JPL applications you have
303 Perl scripts that contain the Perl code to load at runtime.
307 Beware. If you issue the C<make> command and then run the examples
308 in your development directory, you might be in for a surprise! If
309 the JPL directories come first in your CLASSPATH and
310 LD_LIBRARY_PATH, you'll keep running the installed, older version,
311 rather than the one you are developing
315 "Source" means to load it into your current shell, with something
318 C<eval-backtick-setvars-backtick>
320 as opposed to just executing it, because then only the subshell gets
321 the environment vars.
323 =head1 2.3 Calling Perl from Java
325 Now, we'll look at how you can invoke Perl from Java.
327 =head2 2.3.1 Perl Methods
329 You can put Perl methods in your F<.jpl> file. Perl methods are
330 declared C<perl> and use double curly braces to make life easier on
331 the JPL preprocessor:
333 perl int perlMultiply(int a, int b) {{
334 my $result = $a * $b;
338 In your Java code, you can invoke Perl methods like a Java method. The
339 native code wrappers take care of running the Perl code:
341 public void invokePerlFunction() {
344 int retval = perlMultiply(x, y);
345 System.out.println(x + " * " + y + " = " + retval);
351 // A Perl method to multiply two numbers and
352 // return the result.
354 perl int perlMultiply(int a, int b) {{
355 my $result = $a * $b;
359 // A Java method to call the Perl function.
361 public void invokePerlFunction() {
364 int retval = perlMultiply(x, y);
365 System.out.println(x +" * "+ y +" = "+ retval);
368 public static void main(String[] args) {
369 MethodDemo demo = new MethodDemo();
370 demo.invokePerlFunction();
374 =head2 Where did $self go?
376 Don't worry, C<$self> is still there. JPL takes care of fetching it, as
377 well as all the other arguments:
379 perl int perlMultiply(int a, int b) {{
380 my $result = $a * $b;
384 perl void calculateProduct() {{
387 my $retval = $self->perlMultiply($x, $y);
388 print "$x * $y = $retval\n";
391 B<Note>. JPL takes care of putting all the arguments, including
392 C<$self>, into variables. If you see a variable in the function
393 header, you will get a variable of the same name without having to
394 use C<shift> or C<@_>, guaranteed.
398 NOTE: I've added a line that prints the output of "ref dollar sign self"
399 You'll see this when I run the demo.
403 // A Perl method to multiply two values.
405 perl int perlMultiply(int a, int b) {{
406 my $result = $a * $b;
410 // A Perl method to invoke another Perl method.
412 perl void calculateProduct() {{
415 # Ahhh. There's our old friend, $self!
417 my $retval = $self->perlMultiply($x, $y);
418 # Display the results.
420 print "$x * $y = $retval\n";
423 public static void main(String[] args) {
424 SelfDemo demo = new SelfDemo();
425 demo.calculateProduct();
429 =head2 Passing Arrays
431 If you pass an array from Java into a Perl method, it arrives in the
432 form of a scalar reference.
434 Use the GetIntArrayElements() JNI function to convert that scalar into
435 an array of integers.
437 perl void min_max( int[] data ) {{
439 # Get the array elements
441 my @new_array = GetIntArrayElements( $data );
443 # Sort the array numerically
445 my @sorted = sort {$a <=> $b} @new_array;
447 print "Min: $sorted[0], ",
448 "Max: $sorted[$#sorted]\n";
452 int[] data = {101, 99, 42, 666, 23};
456 Some JNI Array Functions
460 =item GetBooleanArrayElements( scalar)
462 Converts scalar to an array of booleans.
464 =item GetByteArrayElements( scalar )
466 Converts scalar to an array of bytes.
468 =item GetCharArrayElements( scalar )
470 Converts scalar to an array of characters.
472 =item GetShortArrayElements( scalar )
474 Converts scalar to an array of short integers.
476 =item GetIntArrayElements( scalar )
478 Converts scalar to an array of integers.
480 =item GetLongArrayElements( scalar )
482 Converts scalar to an array of long integers.
484 =item GetFloatArrayElements( scalar )
486 Converts scalar to an array of floating point numbers.
488 =item GetDoubleArrayElements( scalar )
490 Converts scalar to an array of double precision numbers.
492 =item GetArrayLength( scalar )
494 Returns the length of the array.
499 // Show how to pass an array from Java to Perl.
502 public class PerlTakesArray {
504 perl void min_max( int[] data ) {{
505 # Get the array elements
507 my @new_array = GetIntArrayElements( $data );
509 # Sort the array numerically
511 my @sorted = sort {$a <=> $b} @new_array;
512 print "Min: $sorted[0], ",
513 "Max: $sorted[$#sorted]\n";
517 // Create an array and ask Perl to tell us
518 // the min and max values.
519 int[] data = {101, 99, 42, 666, 23};
523 public static void main(String[] argv) {
524 PerlTakesArray demo = new PerlTakesArray();
530 =head2 2.3.4 Passing Arrays of Objects
532 Working with arrays of objects is a little more complicated, because you
533 need to work with them one at a time.
535 Fetch one element at a time with GetObjectArrayElement(), which returns
536 an object of type java.lang.Object (the most generic type).
538 Explicitly cast the Object to its real type with bless().
540 perl void sortArray( String[] names ) {{
542 for (my $i = 0; $i < GetArrayLength($names); $i++) {
543 my $string = GetObjectArrayElement($names, $i);
544 bless $string, "java::lang::String";
545 push @new_array, $string;
547 print join(', ', sort @new_array), "\n";
551 String[] names = {"Omega", "Gamma", "Beta", "Alpha"};
555 Note. String is not a primitive type: it is a class (java.lang.String).
556 So, you need to use this technique for Strings as well. You can't use
557 the technique in 2.3.3.
559 PerlTakesObjectArray.jpl
561 public class PerlTakesObjectArray {
563 // Perl method to sort an array of strings.
565 perl void sortArray( String[] names ) {{
566 my @new_array; # an array to copy names[] to
568 # Fetch each element from the array.
569 for (my $i = 0; $i < GetArrayLength($names); $i++) {
571 # Get the object (it's not a String yet!) at
572 # the current index ($i).
573 my $string = GetObjectArrayElement($names, $i);
575 # Cast (bless) it into a String.
576 bless $string, "java::lang::String";
578 # Add it to the array.
579 push @new_array, $string;
582 # Print the sorted, comma-delimited array.
583 print join(', ', sort @new_array), "\n";
587 // Create a String array and ask Perl to sort it for us.
591 String[] names = {"Omega", "Gamma", "Beta", "Alpha"};
595 public static void main(String[] argv) {
596 PerlTakesObjectArray demo = new PerlTakesObjectArray();
601 =head2 2.3.5 Returning Arrays from Perl to Java
603 To write a Perl method that returns an array, declare its return value
604 as an array type. Make sure you return a reference to the array, not a
607 perl int[] getTime() {{
608 my ($sec, $min, $hour, @unused) = localtime(time);
609 # Return an array with seconds, minutes, hours
610 my @time_array = ($sec, $min, $hour);
615 int time[] = getTime();
616 System.out.println(time[2] + ":" + time[1]);
621 // Simple JPL demo to show how to send an array to Java
624 class PerlGivesArray {
625 // Call the Perl method to get an array and print
626 // the hour and minute elements.
629 int time[] = getTime();
630 System.out.println(time[2] + ":" + time[1]);
633 // Perl method that returns an array reference.
635 perl int[] getTime() {{
636 # Get the first three arguments from localtime,
638 my ($sec, $min, $hour, @unused) = localtime(time);
640 # Return an array with seconds, minutes, hours
641 my @time_array = ($sec, $min, $hour);
645 public static void main(String[] argv) {
646 PerlGivesArray demo = new PerlGivesArray();
651 =head2 2.3.6 Arrays from Strings
653 JPL will slice Perl strings up into Java arrays for you. If you declare
654 a Perl method as an array type and return a string (instead of an array
655 reference), JPL splits up the elements into an array.
657 Consider this example, where a GIF stored in a string gets turned into
658 an array of bytes so Java can make an Image out of it:
660 void generateImage() {
661 Toolkit kit = Toolkit.getDefaultToolkit();
662 byte[] image_data = mkImage();
663 img = kit.createImage( image_data );
666 perl byte[] mkImage() {{
668 my $im = new GD::Image( $self->width, $self->height);
669 my $white = $im->colorAllocate(255, 255, 255);
670 my $blue = $im->colorAllocate(0, 0, 255);
671 $im->fill($white, 0, 0);
672 $im->string(gdLargeFont, 10, 10, "Hello, World", $blue);
679 import java.awt.event.*;
680 import java.awt.image.*;
683 * A JPL program that demonstrates passing byte arrays
684 * between Java and Perl
688 class GIFDemo extends Canvas {
693 // Constructor for this class.
695 this.setSize(width, height);
698 // Java method to create an image.
700 void generateImage() {
701 Toolkit kit = Toolkit.getDefaultToolkit();
703 // Invoke the mkImage() Perl method to generate an
706 byte[] image_data = mkImage();
708 // Create the image with the byte array we got
709 // from the Perl method.
711 img = kit.createImage( image_data );
714 // A Perl method to generate an image.
716 perl byte[] mkImage() {{
718 # Use the GD image manipulation extension.
722 # Create a new image with the height and width specified
723 # in the enclosing Java class.
725 my $im = new GD::Image( $self->width, $self->height);
727 # Allocate two colors.
729 my $white = $im->colorAllocate(255, 255, 255);
730 my $blue = $im->colorAllocate(0, 0, 255);
732 # Fill the image with white and draw a greeting.
734 $im->fill($white, 0, 0);
735 $im->string(gdLargeFont, 10, 10,
736 "Hello, World", $blue);
740 // Java uses this to repaint the image when necessary.
742 public void paint(Graphics g) {
743 g.drawImage(img, 0, 0, this);
748 public static void main(String[] argv) {
750 // Set up a frame and create an image.
752 Frame f = new Frame("GD Example");
753 f.setLayout(new BorderLayout());
755 GIFDemo demo = new GIFDemo();
756 demo.generateImage();
758 f.add("Center", demo);
759 f.addWindowListener( new Handler() );
767 // A handler to process a request to close a window.
769 class Handler extends WindowAdapter {
770 public void windowClosing(WindowEvent e) {
775 =head2 2.3.7 Summary: Calling Perl from Java
781 Put your embedded Perl code in methods that are declared C<perl>.
785 Use double, rather than single, curly braces ({{ and }}).
789 Invoke the Perl methods from Java just like any other Java method.
793 No need to pull arguments off of C<@_> with C<shift>: JPL takes care of
794 this for you. This includes C<$self>.
798 If you pass a Java array into a Perl method, it comes in as a scalar
803 Convert references to arrays of primitives with C<Get*ArrayElements>
807 Use C<GetObjectArrayElement> to get elements from arrays of strings and
812 To return an array from a C<perl> method, declare the method as returning
813 an array type, and either:
817 Return an array reference.
821 Return a string: JPL slices it up for you.
825 =head1 2.4 Calling Java from Perl
827 Next, let's look at how to invoke Java from Perl.
829 =head2 2.4.1 Java in Perl in Java
831 Remember the issues from 2.1.2 - this is unstable unless you are calling Java from Perl methods that are themselves embedded in a Java program.
833 =head2 2.4.2 Java in Perl: Simple Constructors
835 Use JPL::Class to load the class:
837 C<use JPL::Class "java::awt::Frame";>
839 Invoke the constructor to create an instance of the class:
841 C<my $f = java::awt::Frame->new;>
843 You've got a reference to a Java object in $f, a Perl scalar. I think
846 =head2 2.4.3 Constructors that Take Parameters
848 If the constructor has parameters, look up the method signature with
851 my $new = getmeth("new", ['java.lang.String'], []);
853 The first argument to C<getmeth> is the name of the method. The second
854 argument is a reference to an array that contains a list of the argument
855 types. The final argument to C<getmeth> is a reference to an array
856 containing a single element with the return type. Constructors always
857 have a null (void) return type, even though they return an instance of
860 Invoke the method through the variable you created:
862 my $f = java::awt::Frame->$new( "Frame Demo" );
864 Because Java supports method overloading, the only way Java can
865 distinguish between different methods that have the same name is through
866 the method signature. The C<getmeth> function simply returns a mangled,
867 Perl-friendly version of the signature. JPL's AutoLoader takes care of
868 finding the right class.
870 For example, the method signature for $new is C<(Ljava/lang/String;)V>.
871 In Perl, this is translated to C<new__Ljava_lang_String_2__V>. Sure, it
872 means something to Java, but thanks to C<getmeth> and JPL's AutoLoader,
873 we don't have to worry about it!
875 =head2 2.4.4 More on getmeth
877 The C<getmeth> function is not just for constructors. You'll use it to look
878 up method signatures for any method that takes arguments.
880 To use C<getmeth>, just supply the Java names of the types and objects in
881 the argument or return value list. Here are a few examples:
887 Two int arguments, void return type:
889 $setSize = getmeth("setSize", ['int', 'int'], []);
893 One argument (java.awt.Component), with a return type of the same:
895 $add = getmeth("add", ['java.awt.Component'],
897 ['java.awt.Component']);
901 Two arguments, a String object and a boolean value, and a void return
904 $new = getmeth("new",
906 ['java.lang.String', 'boolean'], []);
910 A String argument with a java.lang.Class return type:
912 $forName = getmeth("forName",
914 ['java.lang.String'],
916 ['java.lang.Class']);
920 No arguments, but a boolean return value:
922 $next = getmeth("next", [], ['boolean']);
926 =head2 2.4.5 Instance Variables
928 Java instance variables that belong to a class can be reached through
929 $self and a method with the same name as the instance variables:
931 $frame->$setSize( $self->width, $self->height );
939 perl int perlChange() {{
940 my $current_value = $self->foo;
942 # Change foo to ten times itself.
944 $self->foo( $current_value * 10 );
948 void executeChange() {
951 System.out.println(foo);
955 public static void main(String[] args) {
957 VarDemo demo = new VarDemo();
958 demo.executeChange();
964 Note. JPL creates these methods with the same name as the variable. You
965 can also supply a value to set the variable's value. If you create a
966 method with this name, it will collide with the one that JPL defines.
971 * FrameDemo - create and show a Frame in Perl.
975 public class FrameDemo {
979 perl void make_frame () {{
981 # Import two Java classes.
983 use JPL::Class "java::awt::Frame";
984 use JPL::Class "java::awt::Button";
986 # Create a Frame and a Button. The two calls to new()
987 # have the same signature.
989 my $new = getmeth("new", ['java.lang.String'], []);
990 my $frame = java::awt::Frame->$new( "Frame Demo" );
991 my $btn = java::awt::Button->$new( "Do Not Press Me" );
993 # Add the button to the frame.
995 my $add = getmeth("add", ['java.awt.Component'],
996 ['java.awt.Component']);
997 $frame->$add( $btn );
999 # Set the size of the frame and show it.
1001 my $setSize = getmeth("setSize", ['int', 'int'], []);
1002 $frame->$setSize($self->width, $self->height);
1007 public static void main(String[] argv) {
1009 FrameDemo demo = new FrameDemo();
1016 =head2 2.4.6 Summary: Calling Java from Perl
1022 Use JPL::Class to specify a Java class to import.
1026 You can directly invoke constructors and methods that take no arguments.
1030 If the constructor or method takes arguments, use getmeth to look up its
1035 Use $self to access Java instance variables and methods.
1041 Copyright (c) 1999, Brian Jepson
1043 You may distribute this file under the same terms as Perl itself.
1045 Converted from FrameMaker by Kevin Falcone.