Creating glue code for the LibWWW
The glue code from C to Tcl of the LibWWW was created to create
Tcl scripts to test the Library. The main software tool utilized isDejaGnu.
The glue code was created for the testing of individual core functions of
the library. With glue code, they became functions in the Tcl interpreter.
The Tcl interpreter was altered to include the glue code. Thus, aside from
testing, the tcl shell can be used to create small applications using
tcl/tk.
The glue code itself follows a standard format:
int function_name_tcl(ClientData clientData, Tcl_Interp *interp,
int argc, char **argv) {
if (argc == 2) {
char *str = argv[1];
....variable initialization....
....function calls...
Tcl_AppendResult(interp, result, NULL);
return TCL_OK;
}
else {
....alert user to improper function call - wrong number of arguments?
return TCL_ERROR;
}
}
The tcl function can be broken up into a number of possible
parts:
Function arguments are treated just like command line arguments
for C. To check the function has the right number of parameters, you check
argc. Otherwise you return an error statement.
All variables in connection to the function need to be
initialized. This includes all variables for the function parameters and
function outputs. Also, there is also the need to initialize enough Tcl hash
table pointers for the number of data structures you have.
This is only used if there are data structures that can't
be represented by the standard things like numbers, characters or strings.
Retrieval involves creating an entry pointer to the hash table with the proper
associated keyname. If there is no such keyname, it will return NULL, which
should be checked for. Then the structures need to be retrieved out of the
table.
Once the data structures are retrieved, the function can
be called with all the necessary parameters.
If there is an output from the function that is a data structure
that needs to be added to the hash table, you store it with a unique keyname.
The keyname should be returned to the tcl interpreter, so it may be called
again.
Since the Tcl interpreter always wants a string output, it
is necessary to convert outputs to strings. For numbers, this just involves
printing the number to a string. For enumerations, the options are to print
the associated value, or create a function to return the proper name. For
data structures, returning the keyname associated with the hash table is
the proper representation.
For any case, where checks do not return the proper boolean,
you should always try to output a string the the Tcl Interpreter describing
the error.
To properly exit the function, and to give Tcl notification
of what kind of failure took place, you should return a Tcl flag. This should
be usually TCL_OK or TCL_ERROR. I believe there are others.
Examples of Tcl glue code.
Adding functions to the library involves creating a main program
which will be a new Tcl interpreter with your functions. Here's a rough coding
of what should be there:
#include "tcl.h" /*This includes the Tcl libraries and Expect Libraries*/
...other includes
Tcl_HashTable hash_table_name /*Intializing hash tables*/
typedef struct{
char *name;
Tcl_CmdProc *proc;
ClientData data;
int flags;
} LibraryFunction;
static LibraryFunction www_commands[] = {
{ "C_function_name", C_function_name_tcl, NULL, 0 },
...other functions...
{0}
};
int main_Init(Tcl_Interp *interp) {
LibraryFunction *c;
/*Hash Table initialization*/
Tcl_InitHashTable(&Hash_Table_name, TCL_STRING_KEYS);
for(c = www_commands; c->name; c++){
Tcl_CreateCommand(interp, c->name, c->proc, c->data,
NULL /* delete proc*/);
}
}
void main_Terminate() {
Tcl_DeleteHashTable(&Hash_Table_name);
}
What's important here is adding the function name to the
www_commands[]. This adds your function to the tcl interpreter.
Standard Methods for variable
input/output:
Boolean Input
int boolean_var;
char *boolean_string = argv[?];
if (Tcl_GetBoolean(interp, boolean_string, &boolean_var)==TCL_OK) {
....body....
}
Integer Input
int input;
char *integer_string = argv[?];
if (Tcl_GetInt(interp, integer_string, &input) == TCL_OK) {
....body....
}
Boolean Output
BOOL result = Somefunction(some_argument);
Tcl_AppendResult(interp, result ? "YES" : "NO", NULL);
Setting a Variable passed in the parameters
In the cases where a pointer to a variable is passed in to a function, and
the assignment must be passed out, use this function from Tcl.
Tcl_SetVar(interp, tcl_var_name, char* newValue, int flags);
alian@mit.edu (neon@w3.org) Alexander Lian. July 19.1996