next up previous contents index
Next: TCL_obj_stl Up: Classdesc Previous: MPISPMD   Contents   Index


TCL_obj

The TCL_obj function creates a set of TCL commands that implement get/set functionality for the class members. For example, with a class definition:

class foo: public TCL_obj_t {int a, b; void foobar(int,char**)} bar;
TCL_obj(&bar,"bar",bar); creates the TCL commands bar.a and bar.b. To set the value of bar.a, use the command bar.a val from TCL. To get the value, use [bar.a].

Also created is the TCL command bar.foobar, which will run respective member function of foo when called from TCL.

As an alternative to (int,char**) arguments for implementing TCL commands, one can also declare the arguments (TCL_args). TCL_args variables can be assigned to numerical variables or strings variables, and the appropriate argument is popped off the argument stack:

int x=args;
double y=args;
assigns the first argument to x and the second to y. This method use the Tcl_Obj structure, so the values needn't be converted to strings at all.

The arguments may also be assigned using the >> operator:

int x; double y;
args >> x >> y;

A third style uses the [] operator:

int x=args[0]; double y=args[1];
The number of remaining arguments is available as TCL_args::count.

If operator>>(istream,T) is defined, then you may also use the >> operator to set a variable of type T, eg:

void foo::bar(TCL_args args)
{
  iarray x;
  args>>x;
}
the assignment operator cannot be used for this purpose, unlike simple types, because nonmember assignment operators are disallowed in the standard. Type conversion operators do not appear to work.

For technical reasons, the name of the TCL command is available as args[-1].

The TCL_obj_t data type also implements checkpoint and restart functions, so that any class inheriting from TCL_obj_t also gains this functionality, as well as client-server functionality.

A helper macro that performs the above is make_model, which is used in a declarative sense, which also initialises the checkpoint functor.

Associated with each of these TCL commands, is an object of type member_entry<T>. Pointers to these objects are stored in a hash table called TCL_obj_properties. The STL hash table behaved rather stangely when used for this purpose, so a class wrapper around TCL hash tables was employed instead:

template<class T>
struct TCL_obj_hash
{
  struct entry 
  {
    entry& operator=(const T& x);
    operator T();
  };
  entry operator[](const char*x);
};
So objects of member_entry<T>* can be inserted into the hash table as follows:
member_entry<T>* m; eco_string d;
TCL_obj_properties[d]=m;
but explicit casts are required to extract the data:
member_entry<T>* m; eco_string d;
m=(member_entry<T>*)(member_entry_base)TCL_obj_properties[d];
Note the double cast is essential! is there anyway to do this more cleanly?.

A utility macro allows these objects to be accessed simply:

declare(name,typename, tcl_name)
where name is the name of a variable (in reality a reference), of type typename that will refer to the variable having the TCL handle tcl_name. The macro performs error checking to ensure such a variable actually exists, and that it is of the same type as typename.

Objects can be placed into TCL_obj_properties by a several different means:

  1. make_model(x), which places all of the leaf objects of x (which must be derived from TCL_obj_t) into TCL_obj_properties, and also completes the construction of the TCL_obj_t object;
  2. register(x), which places x into TCL_obj_properties, as well as the leaf objects -- can also be called as TCL_obj_register(object,object name);
  3. TCLTYPE(typename), where typename is defined C++ type. This creates the TCL command typename, which takes one argument, a variable name for it to be referred to from TCL, and creates an object of that type which it registers in TCL_obj_properties. For example, consider the following code which creates and initialises an object of type distrand and gives it the TCL name PDF (from testdistrand.tcl):
    distrand PDF
    PDF.min -10
    PDF.max 10
    PDF.nsamp 100
    PDF.width 3
    PDF.Init dist
    .....
    PDF.delete
    
    This macro also defines an x.delete procedure for deleting that object, once no longer desired.

A TCL registered object, particularly dynamically created TCLTYPE objects can be assigned to a member of type TCL_obj_ref. This is particularly useful for random number generators:

class Foo: public TCL_obj_t
{
 public:
   TCL_obj_ref<random_gen> rng;

   ...
     rng->rand();
};

Then the member Foo::rng can be assigned an arbitrary random number generator within the TCL script, such as the PDF example above.

distrand PDF
PDF.min -10
...
foo.rng PDF
...

Using TCL_obj_ref also allows that object to be serialised, and to be reconnected after a restart, provided the object has been created prior to the restart.


next up previous contents index
Next: TCL_obj_stl Up: Classdesc Previous: MPISPMD   Contents   Index
Russell Standish 2009-07-01