1

I need to import existing information from tcl files (saved variables in tcl) but I am not familiar with tcl really at all. I need a simple solutions (short), it does not need to be super robust. I have a tcl file that defines a global. Here is a small snippet:

test.tcl:

global gP
set gP(1,1) {-2.77577 -2.66083 14.6978}
set gP(1,2) {-2.2751 -1.91189 13.5285}
set gP(1,3) {-1.46855 -1.21695 11.8953}
...
set gP(1,spline) [list \
  {p (-0.005623,0.225326,4.821360) t (-0.155507,0.806054,-0.571047) tx (0.000000,0.578079,0.815981)} \{p (-0.006889,0.231865,4.816766) t (-0.156976,0.809595,-0.565609) tx (0.000000,0.572709,0.819758)} \
...
  {p (2.224570,6.136620,-6.119510) t (0.901583,0.422393,0.093441) tx (0.000000,0.215995,-0.976394)} \
  ]
...
set gP(1,4) {-0.673205 -0.728409 10.3576}
set gP(1,5) {-0.261822 -0.476418 9.47673}
set gP(1,name) {path1}
...

What I want to do is run tcl from either python or c++ to produce gP in that language. So something like (in python:)

from Tkinter import Tcl
MYFILE = 'test.tcl'
tcl = Tcl()
gP = tcl.evalfile(MYFILE)

My end goal is to get this into c++, but I don't need all of gP. One problem I ran into doing this so far, is that gP is an array, and therefore will not return in the normal way in Tkinter.

This doesn't need to be elegant, I'll only use this once or twice. I am willing to manipulate the variable in python, print out just what I need in a text (or CSV) file, then read that into c++ to populate a variable.

EDIT

Doing this as patthoyts described is a really great start! I think I need one (or two levels of parsing?

I have done this (gPathPoints and gP are the same, different varname only):

a  = eval(tcl.eval('''set r {};
  foreach k [array names gPathPoints] {
    lappend r "'$k': '$gPathPoints($k)'"
  };
  set r "{[join $r ,]}"
  '''))

Python spits out a decent dictionary, but the keys are a little funky:

'100,0': '-2.939 -3.02 15.136',
'100,1': '-2.77577 -2.66083 14.6978',
'100,10': '-0.00681104 0.408274 3.53018',
...

I can probably figure this out with a simple c++ method but I think the following would be easier in tcl:

'100,spline': '{p (-2.939000,-3.020000,15.136000) t (0.242924,0.657821,-0.712923) tx (0.000000,0.734938,0.678134)} {p (-2.934674,-3.008616,15.123467) t (0.250593,0.647200,-0.719955) tx (0.000000,0.743684,0.668531)}
1
  • 1
    There are many ways to do that, an easy way is array get gP after that script runs (Tkinter has an eval function somewhere). The result is a list where the odd elements are the keys and the even elements the value for the previous key. Commented Nov 27, 2013 at 23:05

1 Answer 1

3

Using python:

from Tkinter import *
# create an array in tcl
tk.eval('array set a {a 1 b 2 c 3 d "4 5 6"}')
s = tk.eval('array get a')

This returns the array as a string but using tcl list formatting: 'd {4 5 6} a 1 b 2 c 3' so you need to re-parse this a bit. You can turn it into a python dict by doing that parsing in Tcl quite easily:

a  = eval(tk.eval('''set r {};
  foreach k [array names a] {
    lappend r "'$k': '$a($k)'"
  };
  set r "{[join $r ,]}"
  '''))

using the above example code this yields:

>>> a
{'a': '1', 'c': '3', 'b': '2', 'd': '4 5 6'}
>>> a['d']
'4 5 6'
>>>

You'd have to be more careful about the quoting handling if the array values have embedded quotes but thats simple enough as well.

In C++ I think you may as well evaluate array get $varname to get a Tcl list object. Then you can iterate over the list of key value pairs using Tcl_ListObjGetElements and related functions.

Sign up to request clarification or add additional context in comments.

1 Comment

I'd also point out the Tcl_GetVar2Ex function for reading individual values of an array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.