C/Tcl Interface - How to Write a New Module
This page describes what to do when you want to write a new module in C. It does not describe the programming style
conventions like the usage and capitalization of itendifier names or line widths or such. Of course you are free to
use your own programming style. However, it would be nice, if you keep some standards which make reading the code
by others easier. There are many services offered by the itf module. You should use as many of them as makes sense.
Don't use your own command line parsing or configuration statements etc. as long as the ones that are provided by the
itf module suffice.
This page is still under construction, sorry.
A Modules Structure
If you want to offer anyting in your module that is accessible by Tcl, you should have an initialisation function, that
will be called either by the main() function or by some other initialisation function. In there you can declare your
modules object classes and their methods, and some Tcl commands, if you like. Probably the best way to see how a module
should be build, is to look at an existing one. Sometimes it is even possible to copy most (if not all) of some other
modules code and just modify some identifiers and functions. You could for example take the phones.c file, rename all
"phon" with something else, and you have a new module (we'll sort of). Then you can make modifications to the code and
add new features (and bugs).
Creating Objects
An object can be created in two ways, from Tcl or from C. Objects that are created from C are not automatically
visible from Tcl. The itf module is maintaining a hash table of objects that were created by the user by typing the
appropriate Tcl command. The command objects will list all currently defined objects. An object is defined
from Tcl by entering object-class-name object-name [arguments]
Not all objects need arguments to be created. What arguments are needed depends on the object-class (also called object
type). From C, an object can be created by calling the corresponding creator function. However, Tcl does not know
about this. Generally, one will create the top level objects from Tcl, and the low level objects from C. For example, a
set of codebooks would be created from Tcl, and every single codebook from that set will be created in C. Single
codebooks, as well as other low level objects, can not be created from Tcl because their modules do not register a
creator function for them.
Introducing New Object Types
The easiest way to introduce a new object type, is to look at the code of an already existing type and copy all that is
needed from there. But if tou like, you can also read this document. Here you will find the description of the TypeInfo
structure and the rules for functions that a complete object should provide. Also, you'll find information about optional
services of the itf module.
Register a New Object Type
Before objects of a type can be created, this type must be registered in the itf module. The function
itfNewType is used for this purpose. Its only argument is a pointer to a
TypeInfo structure. The TypeInfo structure contains all information about
the new object type which is of use to the itf module. The most common place to register a type is the modules
init function. You can fill the TypeInfo structure there or you can use the C-compilers
ability to initialize a structure. So somewhere in the modules .c file you'd write:
TypeInfo myObjectInfo = { ... }
MyObject_Init()
{
static in myObjectInitialized = 0;
if (myObjectInitialized==0)
{
/* add initialization calls for other types, here */
if (itfNewType(&myObjectInfo)==TCL_OK)
myObjectInitialized = 1;
else return TCL_ERROR;
}
return TCL_OK;
}
Unregister an Object Type
This is not possible. We did not see any need for such a feature.
What Could/Should an Object Type Be Able to Do
The TypeInfo structure contains pointers to functions that are used for the
maintainace of the objects. These functions are a creator function, a
destructor function, a configurer function, a
subobject accessing function, and a controller function.
Refer to the TypeInfo manual pages for more details about the syntax and usage of these functions and the other
fields of the TypeInfo structure. All of the above functions pointers can either point to an existing
function that does the job, or they can be NULL, which means that the itf module will assume some default
behaviour and perform the task itself.
itf-Functions
Most .c modules will have functions whose names end in Itf. This suffix indicates that these functions
are registered at the itf module. Every object can register itf-Functions, like object creators, destructors, configurers,
etc. This is done by filling an object type structure (TypeInfo) and calling itfNewType(TypeInfo *info).
Usually the itf-Functions will only analyse their command line and call some non-itf-function that performs the actual
task. E.g. you could provide a method for doing 'something'. This would look like:
int moduleMethod (MyType *object, int argc, char *argv[])
{
/* do the 'something' here, return TCL_ERROR on error */
return TCL_OK;
}
int moduleMethodItf (ClientData cd, int argc, char *argv[])
{
if (argc>1) return moduleMethod((MyType*)cd,argv[1]);
else return TCL_ERROR;
}
To make it easier for the reader of the code, you are encouraged to keep up this scheme. Often the
moduleMethodItf() function will use the parseArgs service
of the itf module to parse its command line and then send explicite, possibly somehow processed, arguments to
moduleMethod() instead of argc and argv.
With this scheme of dual entries for every method (or every other function that is accessible from Tcl) we can offer
the same functionality to the C programmer as well as to the Tcl programmer.
Often the itf-functions are one-liners and don't really add much to the code.