Commit | Line | Data |
35ef589f |
1 | =head1 NAME |
2 | |
3 | Tutorial - Perl and Java |
4 | |
5 | =head1 SYNOPSIS |
6 | |
7 | Java and Perl have different strengths and complement each other well. |
8 | |
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 |
11 | vice-versa. |
12 | |
13 | =head2 Note: |
14 | |
15 | Not actually a conversion. |
16 | |
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 |
19 | easier! |
20 | |
21 | =head1 1.1 Perl and Java, Compared |
22 | |
23 | Perl offers rich text processing features, high-level network APIs, |
24 | excellent database integration, and a centralized repository of |
25 | reusable code: |
26 | |
27 | =over 4 |
28 | |
29 | =item * |
30 | |
31 | Regular expression engine is a powerful sub language that can perform |
32 | complex text manipulations and extract data. |
33 | |
34 | =item * |
35 | |
36 | Packages such as libwww-perl (LWP) and libnet are powerful, high-level |
37 | interfaces to network functionality. |
38 | |
39 | =item * |
40 | |
41 | The Perl DBI is an interface to SQL data sources. |
42 | |
43 | =item * |
44 | |
45 | CPAN provides a centralized, organized archive of reusable code. |
46 | |
47 | =back |
48 | |
49 | Java has a powerful graphical API, has numerous embedded |
50 | implementations, excellent database integration, but no single |
51 | recognized repository of reusable code. |
52 | |
53 | =over 4 |
54 | |
55 | =item * |
56 | |
57 | The Swing (JFC) toolkit is a powerful toolkit for developing user |
58 | interfaces. Java also boasts 2D and 3D graphics APIs. |
59 | |
60 | =item * |
61 | |
62 | Java comes in embedded flavors, such as: |
63 | |
64 | =over 4 |
65 | |
66 | =item * |
67 | |
68 | Kaffe C<http://www.transvirtual.com/> - embedded implementations for |
69 | different platforms |
70 | |
71 | =item * |
72 | |
73 | Waba C<http://www.wabasoft.com/> - a subset of Java for Windows CE and |
74 | PalmOS |
75 | |
76 | =item * |
77 | |
78 | It's embedded into web browsers (Netscape and MS Internet Explorer) |
79 | |
80 | =item * |
81 | |
82 | and more... |
83 | |
84 | =back |
85 | |
86 | =item * |
87 | |
88 | Java's JDBC is similar to Perl's DBI |
89 | |
90 | =item * |
91 | |
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 |
94 | repository. |
95 | |
96 | =back |
97 | |
98 | =head1 1.2 Opportunities to Combine Java and Perl |
99 | |
100 | You have a Java program with a lot of data that needs to be parsed, |
101 | filed, briefed, debriefed, and numbered. |
102 | |
103 | You want to build your GUI in Java, but let Perl do the heavy lifting. |
104 | |
105 | You've adopted the "Java is a systems language, Perl is a scripting |
106 | language" paradigm, and it works for you. |
107 | |
108 | You're not sure which regex implementation to use: |
109 | |
110 | C<org.teeth.green.loony.raving.monster.regex.*;> |
111 | |
112 | C<com.zeppelin.regex.*;> |
113 | |
114 | You want the I<B<best of both worlds>>. |
115 | |
116 | =head1 1.3 Important Differences between Java and Perl |
117 | |
118 | =over 4 |
119 | |
120 | =item * |
121 | |
122 | C<perl> compiles and executes programs each time you run them (unless you |
123 | use the Perl compiler). |
124 | |
125 | =item * |
126 | |
127 | C<javac> compiles programs in advance, C<java> runs them in the Java |
128 | interpreter. |
129 | |
130 | =item * |
131 | |
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: |
136 | |
137 | =back |
138 | |
139 | // Draw a circle in the center of the screen |
140 | int drawCircle(int radius); |
141 | |
142 | // Draw a circle at specified coordinates |
143 | int drawCircle(int radius, int h, int k); |
144 | |
145 | =over 4 |
146 | |
147 | =item * |
148 | |
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 |
152 | C<getmeth> function. |
153 | |
154 | =back |
155 | |
156 | =head2 Note: |
157 | |
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. |
161 | |
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. |
168 | |
169 | A subset of JPL now works on Win32. You can embed Java in Perl, but |
170 | you cannot embed Perl in Java (yet). |
171 | |
172 | =head1 2.1 JPL Overview |
173 | |
174 | Let's look at an overview of JPL. |
175 | |
176 | =head2 2.1.1 Calling Perl from Java |
177 | |
178 | Well-supported by JPL, but it is a complicated process: |
179 | |
180 | =over 4 |
181 | |
182 | =item * |
183 | |
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 |
186 | files. |
187 | |
188 | =item * |
189 | |
190 | The C compiler compiles the wrapper and links it to the |
191 | I<libPerlInterpreter.so> shared library, producing a shared library for |
192 | the wrapper. |
193 | |
194 | =item * |
195 | |
196 | The Java compiler compiles the Java source file, which uses native |
197 | methods to load the wrapper. |
198 | |
199 | =item * |
200 | |
201 | The wrapper connects the Java code to the Perl code in the Perl source |
202 | file. |
203 | |
204 | =back |
205 | |
206 | Fortunately, a generic F<Makefile.PL> simplifies the process. This is a |
207 | Perl script that generates a I<Makefile> for you. |
208 | |
209 | =head2 2.1.2 Calling Java from Perl |
210 | |
211 | This works best when Perl is embedded within a Java program. |
212 | |
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. |
215 | |
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 |
221 | library functions. |
222 | |
223 | So, with green threads, you can't reliably embed Java in a standalone |
224 | Perl program. |
225 | |
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. |
228 | |
229 | =head2 Note: |
230 | |
231 | Oddly enough, this is the only way it works on Win32. |
232 | |
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. |
235 | |
236 | |
237 | =head1 2.2 Working with JPL |
238 | |
239 | How to set up a JPL application, compile, and install it. |
240 | |
241 | =head2 2.2.1 Setting up a Project |
242 | |
243 | =over 4 |
244 | |
245 | =item 1 |
246 | |
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 |
249 | JPL applications. |
250 | |
251 | =item 2 |
252 | |
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). |
256 | |
257 | =item 3 |
258 | |
259 | Copy the generic F<Makefile.PL> into the project directory. The |
260 | I<jpl/Sample> directory in the Perl distribution includes the generic |
261 | F<Makefile.PL>. |
262 | |
263 | =item 4 |
264 | |
265 | Write a I<.jpl> program with the same name as the project (such as |
266 | F<Frotz.jpl>) |
267 | |
268 | =back |
269 | |
270 | =head2 2.2.2 Compiling and Installing a Project |
271 | |
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. |
275 | |
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! |
279 | |
280 | Type C<java Frotz> (or the name you chose in step 2 of section 2.2.1) |
281 | to run it |
282 | |
283 | =head2 2.2.3 What's in the jpl Directory? |
284 | |
285 | =over 4 |
286 | |
287 | =item * |
288 | |
289 | B<libPerlInterpreter.so>: a shared library that loads the Perl |
290 | interpreter. |
291 | |
292 | =item * |
293 | |
294 | Compiled F<.class> files for JPL applications you have written. |
295 | |
296 | =item * |
297 | |
298 | Native code shared library wrappers for JPL applications you have |
299 | written. |
300 | |
301 | =item * |
302 | |
303 | Perl scripts that contain the Perl code to load at runtime. |
304 | |
305 | =back |
306 | |
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 |
312 | |
313 | =head2 Note: |
314 | |
315 | "Source" means to load it into your current shell, with something |
316 | like: |
317 | |
318 | C<eval-backtick-setvars-backtick> |
319 | |
320 | as opposed to just executing it, because then only the subshell gets |
321 | the environment vars. |
322 | |
323 | =head1 2.3 Calling Perl from Java |
324 | |
325 | Now, we'll look at how you can invoke Perl from Java. |
326 | |
327 | =head2 2.3.1 Perl Methods |
328 | |
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: |
332 | |
333 | perl int perlMultiply(int a, int b) {{ |
334 | my $result = $a * $b; |
335 | return $result; |
336 | }} |
337 | |
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: |
340 | |
341 | public void invokePerlFunction() { |
342 | int x = 3; |
343 | int y = 6; |
344 | int retval = perlMultiply(x, y); |
345 | System.out.println(x + " * " + y + " = " + retval); |
346 | } |
347 | |
348 | class MethodDemo |
349 | |
350 | class MethodDemo { |
351 | // A Perl method to multiply two numbers and |
352 | // return the result. |
353 | // |
354 | perl int perlMultiply(int a, int b) {{ |
355 | my $result = $a * $b; |
356 | return $result; |
357 | }} |
358 | |
359 | // A Java method to call the Perl function. |
360 | // |
361 | public void invokePerlFunction() { |
362 | int x = 3; |
363 | int y = 6; |
364 | int retval = perlMultiply(x, y); |
365 | System.out.println(x +" * "+ y +" = "+ retval); |
366 | } |
367 | |
368 | public static void main(String[] args) { |
369 | MethodDemo demo = new MethodDemo(); |
370 | demo.invokePerlFunction(); |
371 | } |
372 | } |
373 | |
374 | =head2 Where did $self go? |
375 | |
376 | Don't worry, C<$self> is still there. JPL takes care of fetching it, as |
377 | well as all the other arguments: |
378 | |
379 | perl int perlMultiply(int a, int b) {{ |
380 | my $result = $a * $b; |
381 | return $result; |
382 | }} |
383 | |
384 | perl void calculateProduct() {{ |
385 | my $x = 3; |
386 | my $y = 6; |
387 | my $retval = $self->perlMultiply($x, $y); |
388 | print "$x * $y = $retval\n"; |
389 | }} |
390 | |
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. |
395 | |
396 | |
397 | |
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. |
400 | |
401 | class SelfDemo { |
402 | |
403 | // A Perl method to multiply two values. |
404 | // |
405 | perl int perlMultiply(int a, int b) {{ |
406 | my $result = $a * $b; |
407 | return $result; |
408 | }} |
409 | |
410 | // A Perl method to invoke another Perl method. |
411 | // |
412 | perl void calculateProduct() {{ |
413 | my $x = 3; |
414 | my $y = 6; |
415 | # Ahhh. There's our old friend, $self! |
416 | # |
417 | my $retval = $self->perlMultiply($x, $y); |
418 | # Display the results. |
419 | # |
420 | print "$x * $y = $retval\n"; |
421 | }} |
422 | |
423 | public static void main(String[] args) { |
424 | SelfDemo demo = new SelfDemo(); |
425 | demo.calculateProduct(); |
426 | } |
427 | } |
428 | |
429 | =head2 Passing Arrays |
430 | |
431 | If you pass an array from Java into a Perl method, it arrives in the |
432 | form of a scalar reference. |
433 | |
434 | Use the GetIntArrayElements() JNI function to convert that scalar into |
435 | an array of integers. |
436 | |
437 | perl void min_max( int[] data ) {{ |
438 | |
439 | # Get the array elements |
440 | # |
441 | my @new_array = GetIntArrayElements( $data ); |
442 | |
443 | # Sort the array numerically |
444 | # |
445 | my @sorted = sort {$a <=> $b} @new_array; |
446 | |
447 | print "Min: $sorted[0], ", |
448 | "Max: $sorted[$#sorted]\n"; |
449 | }} |
450 | |
451 | void minMaxDemo() { |
452 | int[] data = {101, 99, 42, 666, 23}; |
453 | min_max( data ); |
454 | } |
455 | |
456 | Some JNI Array Functions |
457 | |
458 | =over 4 |
459 | |
460 | =item GetBooleanArrayElements( scalar) |
461 | |
462 | Converts scalar to an array of booleans. |
463 | |
464 | =item GetByteArrayElements( scalar ) |
465 | |
466 | Converts scalar to an array of bytes. |
467 | |
468 | =item GetCharArrayElements( scalar ) |
469 | |
470 | Converts scalar to an array of characters. |
471 | |
472 | =item GetShortArrayElements( scalar ) |
473 | |
474 | Converts scalar to an array of short integers. |
475 | |
476 | =item GetIntArrayElements( scalar ) |
477 | |
478 | Converts scalar to an array of integers. |
479 | |
480 | =item GetLongArrayElements( scalar ) |
481 | |
482 | Converts scalar to an array of long integers. |
483 | |
484 | =item GetFloatArrayElements( scalar ) |
485 | |
486 | Converts scalar to an array of floating point numbers. |
487 | |
488 | =item GetDoubleArrayElements( scalar ) |
489 | |
490 | Converts scalar to an array of double precision numbers. |
491 | |
492 | =item GetArrayLength( scalar ) |
493 | |
494 | Returns the length of the array. |
495 | |
496 | =back |
497 | |
498 | PerlTakesArray.jpl |
499 | // Show how to pass an array from Java to Perl. |
500 | // |
501 | |
502 | public class PerlTakesArray { |
503 | |
504 | perl void min_max( int[] data ) {{ |
505 | # Get the array elements |
506 | # |
507 | my @new_array = GetIntArrayElements( $data ); |
508 | |
509 | # Sort the array numerically |
510 | # |
511 | my @sorted = sort {$a <=> $b} @new_array; |
512 | print "Min: $sorted[0], ", |
513 | "Max: $sorted[$#sorted]\n"; |
514 | }} |
515 | |
516 | void minMaxDemo() { |
517 | // Create an array and ask Perl to tell us |
518 | // the min and max values. |
519 | int[] data = {101, 99, 42, 666, 23}; |
520 | min_max( data ); |
521 | } |
522 | |
523 | public static void main(String[] argv) { |
524 | PerlTakesArray demo = new PerlTakesArray(); |
525 | demo.minMaxDemo(); |
526 | } |
527 | |
528 | } |
529 | |
530 | =head2 2.3.4 Passing Arrays of Objects |
531 | |
532 | Working with arrays of objects is a little more complicated, because you |
533 | need to work with them one at a time. |
534 | |
535 | Fetch one element at a time with GetObjectArrayElement(), which returns |
536 | an object of type java.lang.Object (the most generic type). |
537 | |
538 | Explicitly cast the Object to its real type with bless(). |
539 | |
540 | perl void sortArray( String[] names ) {{ |
541 | my @new_array; |
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; |
546 | } |
547 | print join(', ', sort @new_array), "\n"; |
548 | }} |
549 | |
550 | void arrayDemo() { |
551 | String[] names = {"Omega", "Gamma", "Beta", "Alpha"}; |
552 | sortArray( names ); |
553 | } |
554 | |
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. |
558 | |
559 | PerlTakesObjectArray.jpl |
560 | |
561 | public class PerlTakesObjectArray { |
562 | |
563 | // Perl method to sort an array of strings. |
564 | // |
565 | perl void sortArray( String[] names ) {{ |
566 | my @new_array; # an array to copy names[] to |
567 | |
568 | # Fetch each element from the array. |
569 | for (my $i = 0; $i < GetArrayLength($names); $i++) { |
570 | |
571 | # Get the object (it's not a String yet!) at |
572 | # the current index ($i). |
573 | my $string = GetObjectArrayElement($names, $i); |
574 | |
575 | # Cast (bless) it into a String. |
576 | bless $string, "java::lang::String"; |
577 | |
578 | # Add it to the array. |
579 | push @new_array, $string; |
580 | } |
581 | |
582 | # Print the sorted, comma-delimited array. |
583 | print join(', ', sort @new_array), "\n"; |
584 | |
585 | }} |
586 | |
587 | // Create a String array and ask Perl to sort it for us. |
588 | // |
589 | |
590 | void arrayDemo() { |
591 | String[] names = {"Omega", "Gamma", "Beta", "Alpha"}; |
592 | sortArray( names ); |
593 | } |
594 | |
595 | public static void main(String[] argv) { |
596 | PerlTakesObjectArray demo = new PerlTakesObjectArray(); |
597 | demo.arrayDemo(); |
598 | } |
599 | } |
600 | |
601 | =head2 2.3.5 Returning Arrays from Perl to Java |
602 | |
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 |
605 | list: |
606 | |
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); |
611 | return \@time_array; |
612 | }} |
613 | |
614 | void testArray() { |
615 | int time[] = getTime(); |
616 | System.out.println(time[2] + ":" + time[1]); |
617 | } |
618 | |
619 | PerlGivesArray.jpl |
620 | |
621 | // Simple JPL demo to show how to send an array to Java |
622 | // from Perl |
623 | |
624 | class PerlGivesArray { |
625 | // Call the Perl method to get an array and print |
626 | // the hour and minute elements. |
627 | |
628 | void testArray() { |
629 | int time[] = getTime(); |
630 | System.out.println(time[2] + ":" + time[1]); |
631 | } |
632 | |
633 | // Perl method that returns an array reference. |
634 | // |
635 | perl int[] getTime() {{ |
636 | # Get the first three arguments from localtime, |
637 | # discard the rest. |
638 | my ($sec, $min, $hour, @unused) = localtime(time); |
639 | |
640 | # Return an array with seconds, minutes, hours |
641 | my @time_array = ($sec, $min, $hour); |
642 | return \@time_array; |
643 | }} |
644 | |
645 | public static void main(String[] argv) { |
646 | PerlGivesArray demo = new PerlGivesArray(); |
647 | demo.testArray(); |
648 | } |
649 | } |
650 | |
651 | =head2 2.3.6 Arrays from Strings |
652 | |
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. |
656 | |
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: |
659 | |
660 | void generateImage() { |
661 | Toolkit kit = Toolkit.getDefaultToolkit(); |
662 | byte[] image_data = mkImage(); |
663 | img = kit.createImage( image_data ); |
664 | } |
665 | |
666 | perl byte[] mkImage() {{ |
667 | use GD; |
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); |
673 | return $im->gif; |
674 | }} |
675 | |
676 | GifDemo.jpl |
677 | |
678 | import java.awt.*; |
679 | import java.awt.event.*; |
680 | import java.awt.image.*; |
681 | |
682 | /* |
683 | * A JPL program that demonstrates passing byte arrays |
684 | * between Java and Perl |
685 | * |
686 | */ |
687 | |
688 | class GIFDemo extends Canvas { |
689 | Image img; |
690 | int width = 200; |
691 | int height = 30; |
692 | |
693 | // Constructor for this class. |
694 | public GIFDemo() { |
695 | this.setSize(width, height); |
696 | } |
697 | |
698 | // Java method to create an image. |
699 | // |
700 | void generateImage() { |
701 | Toolkit kit = Toolkit.getDefaultToolkit(); |
702 | |
703 | // Invoke the mkImage() Perl method to generate an |
704 | // image. |
705 | |
706 | byte[] image_data = mkImage(); |
707 | |
708 | // Create the image with the byte array we got |
709 | // from the Perl method. |
710 | |
711 | img = kit.createImage( image_data ); |
712 | } |
713 | |
714 | // A Perl method to generate an image. |
715 | |
716 | perl byte[] mkImage() {{ |
717 | |
718 | # Use the GD image manipulation extension. |
719 | |
720 | use GD; |
721 | |
722 | # Create a new image with the height and width specified |
723 | # in the enclosing Java class. |
724 | |
725 | my $im = new GD::Image( $self->width, $self->height); |
726 | |
727 | # Allocate two colors. |
728 | |
729 | my $white = $im->colorAllocate(255, 255, 255); |
730 | my $blue = $im->colorAllocate(0, 0, 255); |
731 | |
732 | # Fill the image with white and draw a greeting. |
733 | |
734 | $im->fill($white, 0, 0); |
735 | $im->string(gdLargeFont, 10, 10, |
736 | "Hello, World", $blue); |
737 | return $im->gif; |
738 | }} |
739 | |
740 | // Java uses this to repaint the image when necessary. |
741 | |
742 | public void paint(Graphics g) { |
743 | g.drawImage(img, 0, 0, this); |
744 | } |
745 | |
746 | // The entry point. |
747 | |
748 | public static void main(String[] argv) { |
749 | |
750 | // Set up a frame and create an image. |
751 | |
752 | Frame f = new Frame("GD Example"); |
753 | f.setLayout(new BorderLayout()); |
754 | |
755 | GIFDemo demo = new GIFDemo(); |
756 | demo.generateImage(); |
757 | |
758 | f.add("Center", demo); |
759 | f.addWindowListener( new Handler() ); |
760 | |
761 | f.pack(); |
762 | f.show(); |
763 | |
764 | } |
765 | } |
766 | |
767 | // A handler to process a request to close a window. |
768 | |
769 | class Handler extends WindowAdapter { |
770 | public void windowClosing(WindowEvent e) { |
771 | System.exit(0); |
772 | } |
773 | } |
774 | |
775 | =head2 2.3.7 Summary: Calling Perl from Java |
776 | |
777 | =over 4 |
778 | |
779 | =item 1 |
780 | |
781 | Put your embedded Perl code in methods that are declared C<perl>. |
782 | |
783 | =item 2 |
784 | |
785 | Use double, rather than single, curly braces ({{ and }}). |
786 | |
787 | =item 3 |
788 | |
789 | Invoke the Perl methods from Java just like any other Java method. |
790 | |
791 | =item 4 |
792 | |
793 | No need to pull arguments off of C<@_> with C<shift>: JPL takes care of |
794 | this for you. This includes C<$self>. |
795 | |
796 | =item 5 |
797 | |
798 | If you pass a Java array into a Perl method, it comes in as a scalar |
799 | reference. |
800 | |
801 | =item 6 |
802 | |
803 | Convert references to arrays of primitives with C<Get*ArrayElements> |
804 | |
805 | =item 7 |
806 | |
807 | Use C<GetObjectArrayElement> to get elements from arrays of strings and |
808 | other objects. |
809 | |
810 | =item 8 |
811 | |
812 | To return an array from a C<perl> method, declare the method as returning |
813 | an array type, and either: |
814 | |
815 | =item 9 |
816 | |
817 | Return an array reference. |
818 | |
819 | =item 10 |
820 | |
821 | Return a string: JPL slices it up for you. |
822 | |
823 | =back |
824 | |
825 | =head1 2.4 Calling Java from Perl |
826 | |
827 | Next, let's look at how to invoke Java from Perl. |
828 | |
829 | =head2 2.4.1 Java in Perl in Java |
830 | |
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. |
832 | |
833 | =head2 2.4.2 Java in Perl: Simple Constructors |
834 | |
835 | Use JPL::Class to load the class: |
836 | |
837 | C<use JPL::Class "java::awt::Frame";> |
838 | |
839 | Invoke the constructor to create an instance of the class: |
840 | |
841 | C<my $f = java::awt::Frame->new;> |
842 | |
843 | You've got a reference to a Java object in $f, a Perl scalar. I think |
844 | this is cool. |
845 | |
846 | =head2 2.4.3 Constructors that Take Parameters |
847 | |
848 | If the constructor has parameters, look up the method signature with |
849 | C<getmeth>: |
850 | |
851 | my $new = getmeth("new", ['java.lang.String'], []); |
852 | |
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 |
858 | an object. |
859 | |
860 | Invoke the method through the variable you created: |
861 | |
862 | my $f = java::awt::Frame->$new( "Frame Demo" ); |
863 | |
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. |
869 | |
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! |
874 | |
875 | =head2 2.4.4 More on getmeth |
876 | |
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. |
879 | |
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: |
882 | |
883 | =over 4 |
884 | |
885 | =item * |
886 | |
887 | Two int arguments, void return type: |
888 | |
889 | $setSize = getmeth("setSize", ['int', 'int'], []); |
890 | |
891 | =item * |
892 | |
893 | One argument (java.awt.Component), with a return type of the same: |
894 | |
895 | $add = getmeth("add", ['java.awt.Component'], |
896 | |
897 | ['java.awt.Component']); |
898 | |
899 | =item * |
900 | |
901 | Two arguments, a String object and a boolean value, and a void return |
902 | type: |
903 | |
904 | $new = getmeth("new", |
905 | |
906 | ['java.lang.String', 'boolean'], []); |
907 | |
908 | =item * |
909 | |
910 | A String argument with a java.lang.Class return type: |
911 | |
912 | $forName = getmeth("forName", |
913 | |
914 | ['java.lang.String'], |
915 | |
916 | ['java.lang.Class']); |
917 | |
918 | =item * |
919 | |
920 | No arguments, but a boolean return value: |
921 | |
922 | $next = getmeth("next", [], ['boolean']); |
923 | |
924 | =back |
925 | |
926 | =head2 2.4.5 Instance Variables |
927 | |
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: |
930 | |
931 | $frame->$setSize( $self->width, $self->height ); |
932 | |
933 | Here is an example: |
934 | |
935 | class VarDemo { |
936 | |
937 | int foo = 100; |
938 | |
939 | perl int perlChange() {{ |
940 | my $current_value = $self->foo; |
941 | |
942 | # Change foo to ten times itself. |
943 | |
944 | $self->foo( $current_value * 10 ); |
945 | |
946 | }} |
947 | |
948 | void executeChange() { |
949 | |
950 | perlChange(); |
951 | System.out.println(foo); |
952 | |
953 | } |
954 | |
955 | public static void main(String[] args) { |
956 | |
957 | VarDemo demo = new VarDemo(); |
958 | demo.executeChange(); |
959 | |
960 | } |
961 | |
962 | } |
963 | |
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. |
967 | |
968 | FrameDemo.jpl |
969 | |
970 | /* |
971 | * FrameDemo - create and show a Frame in Perl. |
972 | * |
973 | */ |
974 | |
975 | public class FrameDemo { |
976 | |
977 | int height = 50; |
978 | int width = 200; |
979 | perl void make_frame () {{ |
980 | |
981 | # Import two Java classes. |
982 | |
983 | use JPL::Class "java::awt::Frame"; |
984 | use JPL::Class "java::awt::Button"; |
985 | |
986 | # Create a Frame and a Button. The two calls to new() |
987 | # have the same signature. |
988 | |
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" ); |
992 | |
993 | # Add the button to the frame. |
994 | |
995 | my $add = getmeth("add", ['java.awt.Component'], |
996 | ['java.awt.Component']); |
997 | $frame->$add( $btn ); |
998 | |
999 | # Set the size of the frame and show it. |
1000 | |
1001 | my $setSize = getmeth("setSize", ['int', 'int'], []); |
1002 | $frame->$setSize($self->width, $self->height); |
1003 | $frame->show; |
1004 | |
1005 | }} |
1006 | |
1007 | public static void main(String[] argv) { |
1008 | |
1009 | FrameDemo demo = new FrameDemo(); |
1010 | demo.make_frame(); |
1011 | |
1012 | } |
1013 | |
1014 | } |
1015 | |
1016 | =head2 2.4.6 Summary: Calling Java from Perl |
1017 | |
1018 | =over 4 |
1019 | |
1020 | =item 1 |
1021 | |
1022 | Use JPL::Class to specify a Java class to import. |
1023 | |
1024 | =item 2 |
1025 | |
1026 | You can directly invoke constructors and methods that take no arguments. |
1027 | |
1028 | =item 3 |
1029 | |
1030 | If the constructor or method takes arguments, use getmeth to look up its |
1031 | signature. |
1032 | |
1033 | =item 4 |
1034 | |
1035 | Use $self to access Java instance variables and methods. |
1036 | |
1037 | =back |
1038 | |
1039 | =head1 COPYRIGHT |
1040 | |
1041 | Copyright (c) 1999, Brian Jepson |
1042 | |
1043 | You may distribute this file under the same terms as Perl itself. |
1044 | |
1045 | Converted from FrameMaker by Kevin Falcone. |
1046 | |
1047 | =cut |