Perl komplett

Seit der Entwicklerversion 5.005_54 enthält Perl das Paket "Java Perl Lingo". Es ermöglicht Entwicklern, das Beste zweier Welten zu nutzen: Saubere objektorientierte Softwareentwürfe unter Java und schnell mal eben dahinprogrammierte Perl-Hackereien.

vorlesen Druckansicht
Lesezeit: 9 Min.
Von
  • Jens Ohlig
Inhaltsverzeichnis

Ursprünglich war Java Perl Lingo (JPL) Teil des im Winter 1997 von O’Reilly veröffentlichten Perl Resource Kit für Unix; der Verlag vertrieb es als kommerzielles Produkt. Vor kurzem hat er sich allerdings entschlossen, das Produkt als Open Source freizugeben. Vom ursprünglichen Ziel, einen Perl-nach-Java-Bytecode-Compiler zu implementieren, ist JPL noch entfernt. Trotzdem bietet es reizvolle Möglichkeiten für Programmierer, die in beiden Idiomen entwickeln wollen. Nicht ganz trivial ist allerdings die Installation (siehe "Installation der JPL-Quellen").

Für den Entwickler stellen sich JPL-Programme als Java-Klassen dar, bei denen einzelne Methoden in Perl implementiert sind. Ein Präprozessor namens JPL::Compile erzeugt aus diesem Java/Perl-Gemisch die entsprechenden .java-, .c-, .h-, .pl- and .so-Dateien für die Kompilierung in die endgültige Java-Klassendatei. Das mitgelieferte Perl-Skript jpl automatisiert diesen Vorgang und ruft auch die entsprechenden C- und Java-Compiler auf, so daß sich mit jpl test.jpl eine lauffähige .class-Datei generieren läßt.

Zwischen der Definition einer Java-Methode und der einer in Java eingebetteten Perl-Methode gibt es nur zwei syntaktische Unterschiede. Perl-Methoden werden mit dem Schlüsselwort perl deklariert und die Methode selbst steht in doppelten geschweiften Klammern {{…}}. In JPL sieht das so aus:

perl void EinfacheMethode () {{
print "Hallo, vermischte Java/Perl-Welt.\n";
}}

Um den JPL-Parser nicht zu verwirren, sollte man im Perl-Code zwei geschweifte Klammern hintereinander vermeiden. Statt

perl void EinfacheMethode () {{
if (1) {
if ($variable eq "So nicht") {
print "So geht das nicht.\n"; }}
}}

sollte in der vorletzten Zeile zumindest ein Leerzeichen zwischen den beiden Klammern stehen. Im Prototyp der Methode können wie bei Java beliebige Rückgabetypen, Parameter oder andere Konstrukte erscheinen, etwa Exception-Handling mit throws.

Seine volle Leistungsfähigkeit zeigt JPL, wenn sich beide Sprachen ergänzen und Stärken der einen die Schwächen der anderen ausgleichen. So bietet sich Perl besonders für die Verarbeitung von Texten an, obwohl für Java Klassen zur Behandlung regulärer Ausdrücke verfügbar sind. Wer die Sprachmittel von Perl in Java nutzen will, um eine Mini-Version von grep als Java-Applikation zu erstellen, kann das mit JPL erledigen (siehe Listing 1).

Mehr Infos

Listing 1

// Eine Spar-Version von grep in 
// Perl und Java
public class MiniGrep {
// Zunächst die Methode in Perl...
perl void PerlGrep (String s, String file) {{
open (FILE, "$file");
while (<FILE>) {
print "$s gefunden!\n" if (/$s/);
}
}}
// ... dann main() in Java.
public static void main (String[] argv) {
String s = "root";
String file = "/etc/passwd";
MiniGrep grep = new MiniGrep();
grep.PerlGrep(s, file);
}

Dieses Beispiel demonstriert auch den Zugriff auf einfache Java-Datentypen von Perl. Obwohl Perl nur zwischen skalaren und zusammengesetzten Typen unterscheidet, geht die starke Typisierung von Java bei JPL nicht verloren. Aus einer float-Variablen f macht Perl $f, aus int i wird $i. Zwischen den unterschiedlichen Ideen von "wahr" in beiden Sprachen vermittelt JPL ebenfalls. Javas boolean wandelt es erwartungsgemäß, indem es true in den Perl-Wert 1 und false nach 0 konvertiert. Ist die Perl-Methode als Boolean deklariert, funktioniert das auch umgekehrt. Ein return 1 in Perl gibt true an Java zurück.

Obwohl Perl wie Java mehr oder weniger strenge objektorientierte Sprachen sind (Java mehr, Perl eher weniger) und beider Syntax entfernt an C erinnert, gibt es eine Reihe unterschiedlicher Konzepte, die die beiden trennen. So erlaubt Java das Überladen von Methoden durch unterschiedliche Parametrierung, während bei Perl-Funktionen beliebig viele Argumente einfach im Array @_ verschwinden. Es ist Job der Funktion selbst, @_ auf die korrekte Anzahl von Parametern zu untersuchen, während Java zu viele, zu wenige oder Parameter mit falschem Typ anhand der Methoden-Prototypen erkennt.

Hier kann Perl von Javas stärkerer Objektorientierung profitieren. Für das Mini-Grep-Beispiel oben kann man mit Methodenüberladung zwei Varianten definieren (siehe Listing 2): Entweder gibt die Methode einen Boolean-Wert zurück (true, falls der Ausdruck vorhanden war, sonst false) oder einen Perl-String als byte-Array, das man in einen Java-String konvertieren kann. Es enthält die Zeile, in der der Suchbegriff zuletzt auftauchte. String-Arrays können zwischen den beiden Sprachen leider nicht übergeben werden; JPL unterstützt nur die Übergabe von Arrays primitiver Datentypen.

Mehr Infos

Listing 2

// Zwei gleichnamige Methoden kann
// Java anhand der Parameter unterscheiden:
// Unterschiedliche RĂĽckgabewerte von
// MiniGrep je nach Aufruf in Perl
public class MiniGrep2 {
perl boolean PerlGrep (String s, String file) {{
my $bool = 0;
open (FILE, "$file");
while (<FILE>) {
$bool=1 if (/$s/);
}
return $bool;
}}
perl byte[] PerlGrep (String s) {{
my $byte;
open (FILE, "/etc/passwd");
while (<FILE>) {
chomp;
($byte = $_) if (/$s/);
}
return $byte;
}}
public static void main (String[] argv) {
String s = "root";
String file = "/etc/passwd";
MiniGrep2 grep = new MiniGrep2();
System.out.println("Methode vom Typ boolean");
if (grep.PerlGrep(s, file) == true){
System.out.println("true");
} else {
System.out.println("false");
}
System.out.println("Methode vom Typ byte[]");
byte[] byteArray = grep.PerlGrep(s);
String t = new String(byteArray);
System.out.println(t);
}
}

Perl mit Java-Eigenschaften aufzupeppen, bietet sich auch in anderer Hinsicht an: Durch den Zugriff auf Javas Abstract Windowing Toolkit (AWT) von Perl aus sind grafische Oberflächen für Perl-Scripts denkbar. Zunächst muß das zu importierende Java-Objekt angegeben werden, zum Beispiel so:

use JPL::Class "java::awt::Frame"; 
my $frame = new java::awt::Frame;

Damit Perl jetzt auf andere Methoden als new zugreifen kann, braucht es die Signatur der Methode, die die standardmäßig nach JPL exportierte Funktion getmeth() liefert. Für die void-Methode setTitle von java.awt.Frame mit einem Parameter vom Typ java.lang. String sieht der getmeth()-Aufruf etwa so aus:

my $setTitle = getmeth("setTitle", ["java.lang.String"], []);
# Setze den Titel des Frames
$frame->$setTitle("Mein Titel");

Da JPL massiv vom Java Native Interface (JNI) Gebrauch macht, ist die Entwicklung von Java-Applets nicht ganz so einfach wie dies bei Applikationen der Fall ist. Bei einem Macintosh-Browser, der ein JPL-Applet ausführen soll, dürfte man mit den Shared Libraries einer Linux-Entwicklungsumgebung nichts anfangen können.

Abhilfe für dieses Dilemma kann seit dem JDK 1.1 die Remote Method Invocation (RMI) schaffen, die Zugriff auf Objekte auf anderen Rechnern bietet. Die Entwicklung eines solchen RMI-Applet ist aber aufwendiger als die eines herkömmlichen: Neben dem Applet ist ein RMI-Objekt zu programmieren, das in einer Java Virtual Machine auf dem Server läuft und sich bei der Registry anmeldet. Informationen dazu bietet JavaSoft unter http://www.javasoft.com/products/jdk/1.1/docs/guide/rmi/getstart.doc.html.

Weiterhin kann es Schwierigkeiten bei der Übernahme von Java-Strings in Perl geben. Diese übergibt JPL nicht als einfachen Datentyp, sondern als Referenz auf den Stringinhalt. Das Perl-Modul HTTP::Request prüft allerdings, ob es sich bei dem Parameter um eine Referenz handelt (und versucht, damit in Perl ein eigenes Method-Overloading zu simulieren). Dies kann völlig unterschiedliche Ergebnisse produzieren, je nachdem, ob der Aufruf

$request = new HTTP::Request("GET", $java_url); 

oder

$request = new HTTP::Request("GET", "$java_url&"); 

lautet. Bei der ersten Variante sieht der String fĂĽr HTTP::Request wie eine Referenz aus und das Modul bricht mit einer Fehlermeldung ab. Beim zweiten Aufruf evaluiert Perl den Ausdruck als String, da er in AnfĂĽhrungszeichen eingeschlossen ist, und die Funktion wird korrekt ausgefĂĽhrt.

Signal-Handler und alarm() sollen Programmierer im Perl-Code meiden, rät die Dokumentation. Dadurch sind einige Standardmodule von Perl (wie Net::Ping) nicht benutzbar.

Trotz dieser Schwierigkeiten überwiegen bei JPL die positiven Aspekte. Wenn die Dokumentation jetzt noch außerhalb des erwähnten Perl Resource Kit mit seinem stolzen Preis verfügbar wird, hat JPL gute Chancen, dort einen festen Platz zu erobern, wo die Entwickler sowohl über Java als auch Perl-Know-how verfügen.

JENS OHLIG
studiert am Diplomstudiengang Übersetzen der Universität Bonn und beschäftigt sich außer mit Koreanisch und Englisch intensiv mit verschiedenen Programmiersprachen.