Calling Python code from Tcl is either a Joke (
TIP #365
) or a serious effort
Elmer. In either case, doing this is quite easy with
JTclJust place
Jython on your class path,
export CLASSPATH=/PathToJython/jython.jar
start JTcl, and source the following:
namespace eval ::py {
variable engine
set engManager [java::new javax.script.ScriptEngineManager]
set engine [$engManager getEngineByName python]
}
proc ::py::getResult {value} {
variable engine
if {[java::isnull $value]} {
set result ""
} else {
set class [lindex [[$value getClass] toString] end]
switch -exact $class {
"java.lang.Integer" {
set value [java::cast $class $value]
set result [$value intValue]
}
"java.lang.Double" {
set value [java::cast $class $value]
set result [$value doubleValue]
}
"java.lang.Float" {
set value [java::cast $class $value]
set result [$value doubleValue]
}
"java.lang.Long" {
set value [java::cast $class $value]
set result [$value longValue]
}
"org.python.core.PyTuple" {
set value [java::cast $class $value]
set size [$value size]
set result [list]
for {set i 0} {$i < $size} {incr i} {
lappend result [getResult [$value get $i]]
}
}
default {
set result [$value toString]
}
}
}
return $result
}
proc ::py::do {script} {
variable engine
return [getResult [$engine eval $script]]
}
proc ::py::get {var} {
variable engine
return [getResult [$engine get $var]]
}
proc ::py::put {var value} {
variable engine
if {[string is integer -strict $value]} {
$engine put $var [java::new java.lang.Integer $value]
} elseif {[string is double -strict $value]} {
$engine put $var [java::new java.lang.Double $value]
} else {
$engine put $var $value
}
}
proc ::py::lput {var valueList} {
variable engine
set nElems [llength $valueList]
#set array [java::new {org.python.core.PyObject[]} $nElems $valueList]
set array [java::new {org.python.core.PyObject[]} $nElems]
set i 0
foreach elem $valueList {
if {[string is integer -strict $elem]} {
set jvalue [java::new org.python.core.PyLong $elem]
} elseif {[string is double -strict $elem]} {
set jvalue [java::new org.python.core.PyDouble $elem]
} else {
set jvalue [java::new org.python.core.PyString $elem]
}
$array set $i $jvalue
incr i
}
set pyTuple [java::new org.python.core.PyTuple $array]
$engine put $var $pyTuple
}
proc ::py::alias {name} {
proc ::$name args "
set pargs \[join \$args ,\]
return \[::py::do ${name}(\$pargs)\]
"
}
Then you can do things like::
py::put a 3
py::put b 4
py::do "x = a + b"
puts [py::get x]
py::do {def fib(n):
a, b = 0, 1
while a < n:
print a,
a, b = b, a+b
}
py::do {fib(100)}
py::alias fib
fib 100