View on GitHub

Cpptcl

C++/Tcl, a library that allows to easily integrate C++ and Tcl.

Download this project as a .zip file Download this project as a tar.gz file
[prev][top][next]

Exposing Free Functions

You have already seen an example of how to expose a free C++ function to the Tcl interpreter.
No matter whether you write an extension module or embed Tcl in a C++ application, the way to expose a free function is alway the same:

i.def("tcl_function_name", cpp_function_name);

where i is the name of the interpreter object.
In the above example, the "tcl_function_name" is a name that will be visible to the Tcl scripts and the cpp_function_name is a name of (or a pointer to) the function in the C++ code.
They do not have to be the same, although this is a usual practice, like in the Quick Start examples:

i.def("hello", hello);

In fact, anything that is a valid command name in Tcl can be used as the first parameter.
For example, let's suppose that we want to expose the following C++ function:

int sum(int a, int b) {
  return a + b;
}

later we can define it in the interpreter like this:

i.def("sum", sum);
i.def("+", sum);

so that we can call the sum function from Tcl like this:

add 3 4

or:

+ 3 4

As you see, the same function can be defined in the interpreter more than once, with different Tcl names.
If you try to define some function with the name that is already registered, the old registration will be overwritten.

You have also noticed that the exposed functions can have parameters and return values.
Functions with up to 9 parameters can be exposed.

At the moment, parameters and the return value of exposed functions can have the following types:
In addition, the parameter of the function can be of type T const &, where T is any of the above.
This means that only input parameters are supported (this may change in future versions of the libray).

Starting from version 1.1.4, the last argument of the C++ function can be used to pass an environment data (currently it must be a pointer) to the function, which is realized by using the ClientData field of the Tcl APIs. The following example shows the usage of this extra argument:

// example test7.cc

#include "cpptcl.h"

static int gdata = 2;        // a global data

void fun(int d, int * gd) {  // gd comes from environment
  *gd += d;
}

int main() {
  interpreter i;
  
  i.def("fun", fun, &gdata); // send gdata to the Tcl fun
  
  i.eval("fun 10");          // only one argument is passed by Tcl command
  assert(gdata == 12);       // check the global data is changed

  return 1;
}

For variadic functions, the generic object type should be the second last argument if the last one is used for environment data. Such as:

// a function with 3 typed arguments, one variadic object and one environment data
double fun(int d1, long d2, std::string d3, const object& var_arg, void * any_pointer);