What | JTcl |
Where | https://jtcl-project.github.io/jtcl/ |
Description | An implementation of Tcl written in Java. JTcl implements a large extent of Tcl 8.4 syntax and commands, limited only by API restrictions of the Java Virtual Machine. JTcl is based on the Jacl interpreter. |
Updated | 2015-07 |
Version | 2.8.0 |
JTcl 2.8.0 is released as of July 20, 2015. For a list of changes from the previous version, see: https://jtcl-project.github.io/jtcl/news.html
JTcl and Swank: What's new with Tcl and Tk on the JVM . Presented at the Eighteenth Annual Tcl/Tk Conference (2011).
mh2 Is it still true for JTcl (NOT tclBlend !!) that "tcl interp should have exactly one thread" (that is exactly one thread can call "eval" method of a single tcl interp) ???
TP Yes. However, if you are looking for ways to have concurrency in your JTcl programs, check out the fleet package, written by JTcl maintainer Bruce Johnson. http://jtcl-project.github.io/jtcl/docs/jtcllib/fleet.html Fleet creates a new interpreter and thread for each fleet member, and you communicate with those interp via messages.
mh2 Thanks. In fact I was trying to embed JTcl in "vaadin" (RIA web framework). I didnt know if java listeners can eval tcl code directly, now for each JTcl interp I have a thread with event loop, and java listeners sends events with tcl code to that loop. By the way: I know about great Aejaks software using Echo2, but it seems to me that vaadin has some advantages over echo2: on android browsers vaadin works better than echo2, also vaadin seems to be more extendable (by GWT).
TP The way to handle accessing the JTcl interp from multiple threads is via the event mechanism. Aejaks does this in several places, so it might serve as a guide. If I were doing Aejaks over again today, I would certainly use Vaadin instead of Echo2/3. Feel free to contact me via email or Tcl'ers chat.
MHo 2013-03-01: The tool paraffin.tcl doesn't work for me (Windows XP platform). The command
set jtclJar [ziplib::getClassLocation [java::getinterp]]
gives an unusable filename on windows, with a leading slash '/'. But even working around this, somethings going wrong (did not have the time to look further yet):
c:\Programme\jtcl-2.4.0>jtcl paraffin.tcl iskvprep6 ./iskvprep6 iskvprep6.bat . could not open file ".\echopath": file is not a zip file while executing "error "could not open file \"$fileName\": file is not a zip file"" ("if" then script line 2) invoked from within "if {[java::isnull $ent]} { error "could not open file \"$fileName\": file is not a zip file" }" (procedure "ziplib::openInputZip" line 16) invoked from within "ziplib::openInputZip $jar" invoked from within "set jarin [ziplib::openInputZip $jar]" ("foreach" body line 5) invoked from within "foreach jar $jars { if {! [file isfile $jar]} { continue } set jarin [ziplib::openInputZip $jar] ziplib::c..." (procedure "mkJar" line 22) invoked from within "mkJar $app $srcdir $start $libdir" (procedure "cmdLine" line 32) invoked from within "cmdLine" (file "paraffin.tcl" line 79)
TP Could you file a bug report at http://kenai.com/bugzilla/buglist.cgi?product=jtcl ? Please include Java version, and the pathname of your Java installation. MHo: No, I don't, because doing this requires a login/registration. The JRE used was 1.6.0_41. But the fix could be as simple as this e.g.:
# fix-start if {[string match -nocase windows* $::tcl_platform(os)]} { set jtclJar [string trimleft $jtclJar /] } # fix-end
TP What is the pathname of your Java install? Please attach the output of "parray env" from the JTcl interactive shell. By the way, http://mailinator.com is useful for one-time email addresses :-)
% parray env env(CLASSPATH) = C:\Programme\jtcl-2.4.0\\jtcl-2.4.0.jar;.;C:\Programme\Java\jre1.6.0_07\lib\ext\QTJ ava.zip env(HOME) = D:\Home\Hoffmann env(USER) = HOFFMANN env(awt.toolkit) = sun.awt.windows.WToolkit env(file.encoding) = Cp1252 env(file.encoding.pkg) = sun.io env(file.separator) = \ env(java.awt.graphicsenv) = sun.awt.Win32GraphicsEnvironment env(java.awt.printerjob) = sun.awt.windows.WPrinterJob env(java.class.path) = C:\Programme\jtcl-2.4.0\\jtcl-2.4.0.jar;.;C:\Programme\Java\jre1.6.0_07\lib\ext\QTJ ava.zip env(java.class.version) = 50.0 env(java.endorsed.dirs) = C:\Programme\Java\jre6\lib\endorsed env(java.ext.dirs) = C:\Programme\Java\jre6\lib\ext;C:\WINDOWS\Sun\Java\lib\ext env(java.home) = C:\Programme\Java\jre6 env(java.io.tmpdir) = d:\var\temp\ env(java.library.path) = C:\WINDOWS\system32;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\Progr amme\Tcl\bin;C:\Programme\ActiveState Komodo Edit 7\;C:\Programme\caesar\OraClientNet\bin;C:\Programme\caesar\OraClientN et\;C:\Programme\Python27\;C:\Programme\Python27\Scripts;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\system32\WBEM;c:\Prog ramme\misctool;d:\home\Hoffmann\pgm\tcl\usr\bin;c:\Programme\sysinternals2;C:\Programme\ResKits\Tools\;C:\Programme\Supp ort Tools\;C:\Programme\Pbx;C:\Programme\Perl\site\bin;C:\Programme\Perl\bin;c:\Programme\Regina;C:\Programme\Lua\5.1;C: \Programme\Lua\5.1\clibs;C:\Programme\coreutils;C:\WINDOWS\system32\WindowsPowerShell\v1.0;C:\Programme\ooRexx;C:\Progra mme\Subversion\bin;C:\Programme\Gemeinsame Dateien\Acronis\SnapAPI\;C:\Programme\Citrix\System32\;C:\WINDOWS\system32\Wi ndowsPowerShell\v1.0;C:\Programme\Citrix\System32\;%APPDATA%\Python\Scripts;c:\programme\unix2;C:\programme\texlive\2011 \bin\win32;c:\programme\mingw\bin;c:\Programme\MinGW\msys\1.0\bin;;. env(java.runtime.name) = Java(TM) SE Runtime Environment env(java.runtime.version) = 1.6.0_41-b02 env(java.specification.name) = Java Platform API Specification env(java.specification.vendor) = Sun Microsystems Inc. env(java.specification.version) = 1.6 env(java.vendor) = Sun Microsystems Inc. env(java.vendor.url) = http://java.sun.com/ env(java.vendor.url.bug) = http://java.sun.com/cgi-bin/bugreport.cgi env(java.version) = 1.6.0_41 env(java.vm.info) = mixed mode, sharing env(java.vm.name) = Java HotSpot(TM) Client VM env(java.vm.specification.name) = Java Virtual Machine Specification env(java.vm.specification.vendor) = Sun Microsystems Inc. env(java.vm.specification.version) = 1.0 env(java.vm.vendor) = Sun Microsystems Inc. env(java.vm.version) = 20.14-b01 env(line.separator) = env(os.arch) = x86 env(os.name) = Windows XP env(os.version) = 5.1 env(path.separator) = ; env(sun.arch.data.model) = 32 env(sun.boot.class.path) = C:\Programme\Java\jre6\lib\resources.jar;C:\Programme\Java\jre6\lib\rt.jar;C:\Progr amme\Java\jre6\lib\sunrsasign.jar;C:\Programme\Java\jre6\lib\jsse.jar;C:\Programme\Java\jre6\lib\jce.jar;C:\Programme\Ja va\jre6\lib\charsets.jar;C:\Programme\Java\jre6\lib\modules\jdk.boot.jar;C:\Programme\Java\jre6\classes env(sun.boot.library.path) = C:\Programme\Java\jre6\bin env(sun.cpu.endian) = little env(sun.cpu.isalist) = pentium_pro+mmx pentium_pro pentium+mmx pentium i486 i386 i86 env(sun.desktop) = windows env(sun.io.unicode.encoding) = UnicodeLittle env(sun.java.command) = tcl.lang.Shell env(sun.java.launcher) = SUN_STANDARD env(sun.jnu.encoding) = Cp1252 env(sun.management.compiler) = HotSpot Client Compiler env(sun.os.patch.level) = Service Pack 3 env(user.country) = DE env(user.dir) = C:\Programme\jtcl-2.4.0 env(user.home) = D:\Home\Hoffmann env(user.language) = de env(user.name) = HOFFMANN env(user.timezone) = env(user.variant) = %
TP I think I might see your problem, look at your command line:
c:\Programme\jtcl-2.4.0>jtcl paraffin.tcl iskvprep6 ./iskvprep6 iskvprep6.bat .
The parameters to paraffin.tcl are app-name source-directory start-file [ jar-directory ]
start-file should be the Tcl file that is your main script, not a batch file. jar-directory should be a directory that only contains the additional jar files you need for your application. You are using "." as the jar-directory, which probably contains files other than jar files. Does your application require additional jar files? If so, place all of those jar files in a clean directory.
See the example at: http://jtcl.kenai.com/docs/paraffin.html for more information.
MHo: iskvprep6.bat is a tcl script. Some scripts that I write always start this way:
#!/bin/sh # \ exec /iskv/tools/tclkitsh "$0" ${1+"$@"} ::if 0 { @cls @tclkitsh859.exe "%~dpn0.bat" %* @goto :EOF } : :
And I don't need additional JARs, I think. But of course I will look at the example.
MHo 2013-03-08: Don't know what I made different than before (besides looking at the documentation page which I missed before), but the paraffin step now works ok and produces a .jar file. Running the .jar file gives the following error:
C:\Programme\jtcl-2.4.0>java -jar iskvprep6.jar could not read "resource:tcl/app/iskvprep6.bat": no such file or directory while executing "file mtime [info script" invoked from within "clock format [file mtime [info script]] -format %d.%m.%Y" invoked from within "puts stderr " $script - [clock format [file mtime [info script]] -format %d.%m.%Y] - Anlegen von Unix-Gruppen, -Be nutzern und HomeDirs fuer 21c Aufru..." ("if" then script line 2) invoked from within "if {$argc == 0 || $cIx < 0} { puts stderr " $script - [clock format [file mtime [info script]] -format %d.%m.%Y] -\ Anlegen von Unix-Gruppen, -Benu..."
TP This error is from the file command not understanding the resource: convention. Instead of a true virtual file system (like C/Tcl), JTcl only recognizes resource: in open and source commands. To make this work, you'll have to modify your application to not use file on a resource: pathname.
MHo: Then, how to get the filetime of the script itself?
TP Unfortunately, there's not an easy way. The included package ziplib has a library command to open and traverse a zip or jar file. See the second example at: http://jtcl.kenai.com/docs/jtcllib/ziplib.html Instead of using the getName method, use getTime, which will return the zip entry's modification time in milliseconds.
MHo 2015-01-13: Could not figure out how to get the directory from which the script (in this case inside the jar file) is running, as the usual methods (argv0, info script, etc.) of course don't work as expected. But often there are files alongside the jar which needs to be processed, and you don't always know from where the script is being called. Specifying absolute paths is not an option. The only workaround I found so far is: [file dirname [lindex [split $env(java.class.path) \;] 0]]].