6

Tcl 8.4

In my Tcl script:

set foo1 false set foo2 "yes" set foo3 [list item1 item2 item3] 

There's a API to get scalars like foo1 or foo2. Eg: Tcl_GetVar(tcl_interp, string("foo1").c_str(), flags). I was wondering if there's any API to get list (like foo3) from Tcl?

1
  • 1
    Note that Tcl's API is a C API, not a C++ one. That means it has a number of idioms that are distinctly clunky from a C++ perspective. AFAIK, nobody's produced the definitive C++ adaptation of the Tcl API yet (or at least they've not made it and kept it maintained). Commented May 31, 2012 at 12:18

3 Answers 3

7

It's a two-stage thing. You first fetch the value with one of the Tcl_GetVar family of functions, then you get the pieces of the list that you're interested in (with Tcl_SplitList or Tcl_ListObjGetElements, normally).

As a more concrete example:

////// FETCH FROM VARIABLE ////// // The NULL is conventional when you're dealing with scalar variable, // and the 0 could be TCL_GLOBAL_ONLY or Tcl_Obj *theList = Tcl_GetVar2Ex(interp, string("foo1").c_str(), NULL, TCL_LEAVE_ERR_MSG); if (theList == NULL) { // Was an error; message in interpreter result... } ////// EXTRACT ELEMENTS ////// int objc; Tcl_Obj **objv; if (Tcl_ListObjGetElements(interp, theList, &objc, &objv) == TCL_ERROR) { // Not a list! error message in interpreter result... } ////// WORK WITH VALUES ////// for (int i=0 ; i<objc ; i++) { const char *value = Tcl_GetString(objv[i]); // Whatever... } 
Sign up to request clarification or add additional context in comments.

1 Comment

If you use the older purely string-based API, you'll end up with using Tcl_SplitList. That has an “unusual” feature in that you have to Tcl_Free the array of strings, and it's really not very convenient. It's also way slower than the Tcl_Obj-based API.
1

I'm not sure, but Tcl_ListObjGetElements looks like what you want. Or, alternatively, Tcl_ObjGetVar2 would return a Tcl_Obj which you could then manipulate using the rest of the Tcl API for working with list objects.

1 Comment

Tcl_GetVar2Ex is often most convenient.
-1

Hi i have found this useful link containing an example for dealing the list:

Reference:: https://www.tcl.tk/man/tclx8.2/TclCommandWriting.3.html

int Tcl_LreverseObjCmd(notUsed, interp, objc, objv) ClientData notUsed; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj **obj; /* Argument strings. */ { int listObjc, lowListIndex, hiListIndex; Tcl_Obj **listObjv; char *temp, *resultList; Tcl_Obj **newListObjv; /* Verify argument count. Since we take only one argument, argument * count must be 2 (command plus one argument). */ if (objc != 2) return TclX_WrongArgs (interp, objv [0], "list"); /* Create an object to handle the new list we're creating */ newListObjv = Tcl_NewObj(); /* Crack the list at objv[1] into its own count and array of object * pointers. */ if (Tcl_ListObjGetElements (interp, objv[1], &listObjc, &listObjv) != TCL_OK) { return TCL_ERROR; } /* For each element in the source list from last to first, append an * element to the new list. */ for (listIndex = listObjc - 1; listIndex >= 0; listIndex--) { Tcl_ListObjAppendElement (interp, newListObjv, listObjv[listIndex]); } FIX: NEED TO RETURN THE LIST. return TCL_OK; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.