const Adding application specific variablesAdding application specific variablesOrdinary Tcl Variables

Ordinary Tcl Variables

Ordinary TCL variables are presented to the C++ code as objects of the class CTCLVariable. Creating an ordinary TCL Variable requires that you:

Suppose, for example, that you want to create a boolean variable (legal values 0,1), that controls whether or not a piece of the detector system is installed (and therefore readout or not). Your declaration of CMyExperiment would include member data for that variable and a way to get a reference:

	    class CMyExperiment : public CReadoutMain
	    {
	       private:
		  CTCLVariable m_Present;
		  ...
	       public:
		  CMyExperiment() :
		     m_Present(string("present",false)){}
		  ...
	       public:
		  CTCLVariable& getPresentVariable() {
		     return m_Present;
		  }
		  ...
	    };
	 

In AddUserCommands, you know that the Tcl interpreter exists and can be manipulated, therefore you add code to register and initialize the variable:

	    ...
	       CTCLInterpreter* pInterp = rStartup.getInterpreter();
	       m_Present.Bind(*pInterp);
	       m_Present.Set("0", TCL_GLOBAL_ONLY);
	    ...
	 

Once you have created a variable, you can access it in two ways:

Which you choose depends on your performance needs. If you are only setting or getting the variable's value occaisionally, using the Get or Set is probably the best approach. If, however you are accessing this variable each time you read an e event, you should bind the variable to a C/C++ variable.

Using Get and Set

The following code fragment shows how to get the value of the variable "presetn" using the Get and Set functions:

	    ...
	    
	    // Get the value of the present variable
	       
	    CMyExperiment* pExp = 
	       (CMyExperiment*)CReadoutMain::getInstance();
	    CTCLVariable p(pExp->getPresentVariable());
	    CTCLInterpreter* pInterp = p.getInterpreter();
	    const char* Value = p.Get(TCL_GLOBAL_ONLY);
	    Bool_t bValue = pInterp->ExprBoolean(Value);
	       
	    ...
	    // Set present variable with bValue:
	    CMyExperiment* pExp = 
	       (CMyExperiment*)CReadoutMain::getInstance();
	    CTCLVariable p(pExp->getPresentVariable());
	    p.Set(bValue ? "1" : "0", TCL_GLOBAL_ONLY);
	    
	    ...
	 
Binding TCL variables to C/C++ variables.

To bind a TCL Variable to a C++ variable, you must make the variable either member data for an object that will live for the lifetime of the program, or a file scoped or globally scoped variable. Bound variables are "typed" and the Tcl interpreter prevents the user from setting them to an inappropriate string for the type (e.g. an int cannot be set to "hi there"). Only one C/C++ variable can be bound to a Tcl variable. Binding a second unbinds the first.

The code fragment below shows how to bind the Tcl Present variable to a C/C++ variable.

	 ...
	 Bool_t bValue;         // Bind to this.
	 ...
	 
	 {               // Some function body.
	    ...
	    CMyExperiment* pExp = 
	       (CMyExperiment*)CReadoutMain::getInstance();
	    CTCLVariable p(pExp->getPresentVariable());
	    p.Link(&bValue, TCL_LINK_BOOLEAN);
	    ...
	 }
	 ...
	 

Once linked, bValue will reflect the current value of the Tcl Variable, and scripted references to "present" will reflect the value of bValue.

If your scripts monitor bValue via traces or you have a widget that is monitoring bValue (e.g. via -textvariable or -variable), you must ensure that when the variable is modified, you eventually call (CTCLVariable::Update) to fire Tcl's traces:

	    ...
	    CMyExperiment* pExp =
	       (CMyExperiment*)CReadoutMain::getInstance();
	    pExp->getPresentVariable().Update();
	    
	    ...
	 

Report documentation errors to Ron Fox (fox@nscl.msu.edu)or NSCL's Bugzilla page

const Adding application specific variablesAdding application specific variablesOrdinary Tcl Variables