tcl_c++: an Interface Between tcl and c++
c++_tcl architecture.
This software allows a c++ programmer to create a tcl interface to c++
objects
with minimal coding overhead (basically one line per member function). The
name of the class becomes a tcl procedure (with or without arguments
depending on what constructors are defined) that calls the appropriate
constructor and creates a
tcl procedure to interface to the newly created object.
This tcl procedure uses its first argument to decide which member function
of the object to call. The value of variables and constants are also
available to tcl programs. Multiple inheritance is supported.
To use tcl_c++ you must create a file
called myClassTCL.tcl for each c++ class, for example:
startClass myClass
constructor
constructor int double
memberFunction void member
memberFunction int integer
memberFunction int integerArgument int
memberFunction myClass* pointerArgumentReturn myClass*
memberFunction myClass& referenceArgumentReturn myClass&
memberFunction void twoArguments int char*
memberFunction int* handlePointers double*
memberConstant double doubleConstant
memberVariable int integerVariable
destructorCommand delete
baseClass baseClass1
baseClass baseClass2
endClass
Note: only the parts of the class that should be available to tcl
are put in the file.
This file is actually a tcl program. The tcl procedures
startClass, constructor, memberFunction and so forth are
defined in a file called convert.tcl.
Now for the explanations:
- startClass myClass -- the class is named "myClass". This must
always come first.
- constructor -- there is a constructor with no arguments. If no
constructors are specified, this default constructor is created
unless the tcl variable abstractClass is non-zero.
In this case no constructors are allowed.
- constructor int double -- there is a constructor with two arguments,
an int and a double. One might say: "set object [myClass 1 2.4]".
Note that $object will be a number -- specifically the value of
a pointer pointing to the object created. $object will also be a tcl
procedure whose first argument will determine which member function,
constant, or variable will be accessed.
- memberFunction void member -- this creates
an interface to a member function named "member" with no arguments and
no return value. Note that at present member function
dispatch is on name and number of arguments
only -- not type. This could be fixed by changing convert.tcl output to optionally
look for lists containing
the type followed by the value each time a member function is called.
- memberFunction int integerFunction -- this member function returns
an integer.
- memberFunction int integerArgument int -- this one also takes
an integer as an argument.
- memberFunction myClass* pointerArgumentReturn myClass* -- this function
takes a pointer as an argument and returns a pointer.
- memberFunction myClass& referenceArgumentReturn myClass& -- this one
handles reference arguments and return values (the return value is
just a number that is the address of the returned object). This only works
if
myClass is derived from the tcl_c++ support class
aTclCapableClass. aTclCapableClass doesn't do anything or allocate
any memory, but it's necessary as a base class so the tcl_c++
generated code handles types properly.
- memberFunction void twoArguments int char* -- this member function
takes two arguments. Note that char* has no spaces. This is necessary
to have tcl consider it one argument. Alternatively, one could use
"char *" (enclose it in double quotes).
- memberFunction int* handlePointers double* --
this function takes a pointer to a double as an argument (probably
returned by a memberFunction) and returns a pointer to an integer.
As far as tcl is concerned, the return value and argument are simply
numbers. C++ knows that these numbers are pointer values.
- memberConstant double doubleConstant -- this creates an interface
so tcl can get the value of a constant. The code might look like
"set value [$object doubleConstant]". This works for static and non-static
member constants.
- memberVariable int integerVariable -- same as memberConstant.
It will only return the value. To set the value
you must write a member function. This works for static and non-static
member variables.
- destructorCommand delete -- "$object delete" will call
the myClass destructor and tclDeleteCommand (see below).
This is not well tested.
- baseClass baseClass1 -- myClass has a base class accessible
from tcl.
- baseClass baseClass2 -- myClass has a second base class accessible
from tcl. Member functions from baseClass1 will be used if there's a
name conflict because baseClass1 is first.
At present, the baseClass calls must come at the end.
- endClass -- signals the end of the class interfaces.
This must always come last.
Note the following issues:
- tcl_c++ assumes that there is an include file called
myClass.hh. If not, use "set includeFileName
actual-include-file-name" before the startClass call. If
includeFileName == "none", no class specific #include will be in the c++ file.
- To put custom code in the generated c++ file, use "puts" anywhere in your
myClassTCL.tcl file.
- It's best if the classes you interface to are derived from aTclCapableClass.
aTclCapableClass has no
members so it should cause no problems as a base class. If you don't use
aTclCapableClass as a base class, you won't
be able to pass or return references to your class (pointers should work though).
Note that classes without aTclCapableClass as a base class haven't been well tested.
- Pointers to most pre-defined types will have tcl names equal to their address.
Char* is an exception, these are always handled as constant strings.
- Every class automatically has a tcl "member function" called tclDeleteCommand.
When this is called, the tcl command created for the object will be replaced
with an error message. This allows tcl to forget about objects.
- If a member function returns an object that does not have a tcl command,
the tcl program won't be able to access this object's members.
This can be fixed by using the automatically generated tcl procedure
"cast2myClass" with one argument -- a pointer to the object (presumably
returned by a member function). cast2myClass creates a tcl
procedure to interface to the object, which is assumed to be an
instance of myClass. Note that there is no type checking.
Known problems:
- Const has never been tested in any context.
- Unsigned anything and long double arguments and return values aren't supported.
- Operators and non-member functions, constants and variables
aren't supported.
- tcl_c++ doesn't check to see if input numbers are really numbers.
- tcl_c++ isn't thread compatible.
- The build generates a number of unimportant c++ error messages.
- tcl_c++ puts a few name constraints on your c++ software. Namely, there can
be no class members named aTclCommand_argument followed by a number.
Also, there may be no functions called _myClass__handleMemberFunctionsTclCommand.
These restrictions shouldn't be too severe.
- There is one constraint on the names of tcl procedures you can use,
cast2myClass is automatically created for each class.
- Memory management issues haven't been carefully address or tested.
Only the c++ delete operator is directly supported, not reference counting schemes.
One can call a member function and then use tclDeleteCommand though.
- Tcl_c++ has only been tested on IRIX 5.3.
I had hoped to distribute the code on the WWW, but it's not quite
ready for wide distribution -- especially the regression test. If you
are interested in using tcl_c++, send email to globus@nas.nasa.gov.
To the NanoDesign paper.
Author: Al Globus