Open Source im professionellen Einsatz
Linux-Magazin 11/2004

Jacl und Tclblend verbinden Tcl und Java

Fremde Federn

Java und Tcl ergänzen sich bestens und profitieren voneinander: Ein Testskript für eine Java-Applikation ist in Tcl schneller geschrieben als in Java. Andererseits wollen Tcl-Entwickler gelegentlich Java-Pakete nutzen. Jacl und Tclblend geben ihnen diese Freiheiten.

1081

Die Programmiersprachen Java und Tcl sind längst feste Größen in der Welt der Compiler und Skripte. Doch auch eingefleischte Anhänger der einen Welt können kaum die Vorzüge der jeweils anderen verhehlen. Oft wäre es praktisch, in einem Tcl-Programm zusätzlich auf Java-Pakete und -Klassen zuzugreifen oder ein Java-Programm um Tcl-Scripting-Fähigkeiten zu ergänzen. Die Brücke zwischen beiden Welten schlagen Jacl und Tclblend, beide Softwarepakete des Tcljava-Projekts[1].

Jacl ist eine komplett neue Implementation des Tcl-Interpreters in reinem Java. Er führt Tcl-Skripte bis auf wenige Ausnahmen so aus, als ob sie in der normalen C-basierten Tclsh liefen. Ähnliches gibt es auch für andere Skriptsprachen wie Python (Jython,[3]) oder ECMA-Script/Javascript (Rhino,[4]). Je nach Aufgabe startet die Java-Anwendung den Interpreter mit einem Skript oder das Skript kontrolliert den Ablauf und greift auf Java-Methoden zu.

Jacl

Ioi Lam begann als Student in Cornell damit, den Tcl-Interpreter in Java neu zu schreiben. Inzwischen arbeitet vor allem Mo DeJong von Red Hat an Jacl. Bruce Johnson ergänzte mit seinem Swank[2] noch eine Tk-Variante, die er ebenfalls in reinem Java implementiert hat. Als Java-Software lassen sich Jacl und Swank über Java Webstart ausprobieren. Wer darin die Tkcon startet, hat eine komfortable Tcl-Shell frei Haus. Dazu muss eine JVM installiert sein, insbesondere für Webstart sollte es allerdings eine aktuelle Version (1.4.2) sein.

In Abbildung 1 ist die Java-Version der Tkcon zu sehen. Mit dem Tcl-Kommando »puts« hat der Benutzer zunächst einen Hallo-Welt-Text ausgegeben (blau dargestellt) und dann mit mehreren Tk-Kommandos ein weiteres Fenster mit einem Button erzeugt. Dank Swank ist das Fenster tatsächlich mit Swing- und nicht mit nativen Tk-Widgets gebaut. Sogar die Systemvariablen im »env«-Array entsprechen den Java-System-Properties, nicht den normalen Tcl-Werten.

Die Installation von Jacl und Swank gelingt am einfachsten mit der Tar-Datei von Swank[2], sie enthält bereits alle notwendigen Java-Bibliotheken sowie die Startskripte. Nach dem Auspacken startet der Aufruf »./wisk Skriptname« ein Skript im Interpreter, ganz wie bei »wish«. Die Swank-Distribution enthält unter anderem das Skript »swkon.tcl«, es handelt sich um die Java-Version der Tkcon (in Abbildung 1 benutzt).

Abbildung 1: Die Tkcon läuft hier als Java-Anwendung: Interpreter und Widget-Set sind in reinem Java implementiert. Der Benutzer kann dennoch normale Tcl- und Tk-Kommandos eintippen (links) und damit zum Beispiel neue GUIs gestalten (rechts).

Tcl und Tk auf Java-Basis statt mit C ist technisch interessant - damit sollte es sogar möglich sein, Tcl auf einem Java-fähigen Handy zum Laufen zu bringen. Weitaus wichtiger ist jedoch der Zugriff auf die jeweils andere Sprache.

Federführend

Für den Zugriff von Tcl auf Java ist ein Tcl-Paket namens »java« zuständig. Es enthält Funktionen, mit denen ein Tcl-Programm Java-Objekte und -Methoden aufrufen kann. Listing 1 zeigt ein Tcl-Skript, das die Java-Klasse in Listing 2 verwendet. Die Klasse enthält neben einfachen Getter- und Setter-Methoden (Beans-Konzept) auch mehrere Konstruktoren, statische Variablen und überladene Methoden.

Listing 1: Java-Objekte in
Tcl

01 # Benutzt die Java-Klasse "Demo" aus Listing 2
02 
03 package require java
04 set env(TCL_CLASSPATH) "."
05 
06 # statische Variable
07 puts "Demo.NAME '[java::field Demo NAME]'"
08 
09 # statische Methode
10 set instance0 [java::call Demo getInstance "Statisch"]
11 puts "Aufruf getInstance '[java::prop $instance0 a]'"
12 
13 # Objekt erzeugen
14 set instance [java::new Demo "Erstes Objekt"]
15 
16 # Wert abfragen und ändern
17 puts "Bean-Style '[java::prop $instance a]'"
18 java::prop $instance a "Geänderter Name"
19 puts "Bean-Style '[java::prop $instance a]'"
20 
21 # Methode aufrufen
22 puts "Getter-Aufruf '[$instance getA]'"
23 puts "Aufruf von methode, Ausgabe '[$instance methode]'"
24 puts "Aufruf von toString, Ausgabe '[$instance toString]'"
25 
26 # überladene Methode
27 catch {$instance überladen 1} err
28 puts stderr $err
29 
30 puts "Eingabe als Integer, Ausgabe '[$instance {überladen int} 42]'"
31 puts "Eingabe als Double, Ausgabe '[$instance {überladen double} 42.0]'"
32 
33 # Fehler fangen
34 foreach wert {0 1 2 3} {
35   puts -nonewline "Eingabe für Methode fehler='$wert'"
36   java::try {
37     puts ", Ausgabe '[$instance fehler $wert]'"
38   } catch {IllegalArgumentException iaexp} {
39     puts stderr ", Eingabefehler '[$iaexp getMessage]'"
40   } catch {IllegalStateException isexp} {
41     puts stderr ", Interner Fehler '[$isexp getMessage]'"
42   } catch {Exception exp} {
43     puts stderr ", Fehler '[$exp getMessage]'"
44   }
45 }
46 
47 # gegen null prüfen
48 set b [java::prop $instance b]
49 if [java::isnull $b] {
50   puts "B ist null"
51 }
52 
53 # Objektreferenzen in Java verwenden
54 set instance2 [java::new Demo "Zweites Objekt" $instance]
55 puts "toString '[$instance2 toString]'"

Listing 2: Benutzte
Java-Klasse

01 // Demo.java
02 import java.awt.event.*;
03 
04 /**
05  * Beispielklasse für Tcl/Java-Integration
06  */
07 public class Demo {
08   public static final String NAME = "Demo";
09   private String a;
10   private Demo b;
11   private int c;
12 
13   public Demo (String a) {
14     this.a = a;
15   }
16   public Demo (String a, Demo b) {
17     this.a = a;
18     this.b = b;
19   }
20   public static Demo getInstance (String a0) {
21     return new Demo(a0);
22   }
23 
24   public void   setA (String a) {this.a = a;}
25   public String getA ()         {return a;}
26   public Demo   getB ()         {return b;}
27   public void   setC (int c)    {this.c = c;}
28   public int    getC ()         {return c;}
29 
30   public String fehler (long a) {
31     if (a>0) {
32       if ( (a%3) == 0 ) {
33         throw new IllegalArgumentException ("teilbar durch 3");
34       } else if ( (a%2) == 0 ) {
35         throw new IllegalStateException ("teilbar durch 2");
36       }
37     }
38     return String.valueOf (1/a);
39   }
40 
41   public long methode() {
42     return System.currentTimeMillis();
43   }
44   public String toString() {
45     return (b == null) ? a : (b.toString( ) + a);
46   }
47 
48   public String überladen (int a)    {return String.valueOf(a/2); }
49   public String überladen (double a) {return String.valueOf( a ); }
50 }

Nach dem üblichen »package require java« (Zeile 3 in Listing 1) steht in Tcl eine Reihe neuer Kommandos im Namensraum »java« zur Verfügung. Eine Zusammenfassung der Befehle zeigt Tabelle 1. Damit Jacl die zusätzlichen Java-Klassen findet, setzt das Tcl-Skript in Zeile 4 einen zusätzlichen Classpath. Alternativ könnte man vor dem Start der JVM auch die globale »CLASSPATH«-Variable ändern.

Tabelle 1: Wichtige
Kommandos des Java-Pakets

 

Kommando

Aufgabe

java::new Klassenname Argumente

Erzeugt neue Java-Objekte

java::call Klassenname Methodenname Argumente

Ruft statische Methoden auf

java::field Klasse/Objekt Feldname [Wert]

Fragt oder setzt Objektattribute

java::instanceof Java-Objekt Klassenname

Wie »instanceof« in Java

java::prop Java-Objekt Name [Wert]

Fragt oder setzt Bean-Style-Attribute

java::bind Java-Objekt Event-Name Skript

Bindet ein Tcl-Skript an einen Java-Event

java::null

Gibt das Java-Objekt »null« zurück

java::isnull Objekt

Testet Java-Objekt gegen »null«

java::throw Throwable

Wirft eine Java-Exception

java::try Skript catch { Klassenname Variable}
Skript finally Skript

Das Äquivalent zu Javas Try/Catch/Finally-Konstrukt

java::cast Klassenname Java-Objekt

Äquivalent zu Java »cast«

java::import Klassen/Paketname

Äquivalent zu Java »import«

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Zu neuen Ufern

    Das nächste JDK soll Java modernisieren. Ob das Ergebnis den Versionssprung auf 5.0 rechtfertigt oder ob er sich als Marketing erweist, verrät dieser Ausblick auf die bevorstehende Java-Release.

  • Mit Schwung - ohne Swing

    Linux wird auf dem Desktop salonfähig, von Java ist dies leider nicht zu behaupten, zu gründlich wurde der Ruf schon vor Jahren ruiniert. Mit den Java-Language-Bindings ist aber eine performante und saubere Integration in das K Desktop Environment möglich.

  • Kaffee im Open Office

    Ohne Kaffee läuft in deutschen Büros nichts. Der Beitrag beweist, dass auch Open Office mit Java viel leistet: Das Open-Office-SDK liefert ein Rezept für das belebende Gebräu.

  • Java mixen

    Bei Java interessiert nicht nur die Bohne, auch die reiche Vielfalt an Bibliotheken und Frameworks hält die Sprache wach. Und wem der Sinn nach einer Melange steht – Java integriert Fremdsprachen aller Geschmacksrichtungen.

  • Java

    Die Vorbeugung gegen Datendiebstahl und illegale Zugriffe spielt bei der Anwendungsentwicklung eine immer größere Rolle. Der Java-Programmierer findet in der Java-SE-Security-Bibliothek, was er braucht, um Daten zu ver- und entschlüsseln sowie Prüfsummen und Signaturen einzusetzen.

comments powered by Disqus

Ausgabe 04/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.