1. CAPI
CAPI is used to translate Tcl to C in order
to use the application programming interface in Wize.
CAPI differs from other approaches to auto-extending Tcl
(eg. CRITCL) due to its
focus on Tcl argument interface semantics.
Its goal
is to radically simplify translation and
provide
automatic argument unloading and type checking.
CAPI accomplishes this by
leveraging on the Types facility built in to Wize.
This allows it to automatically
generates stub C code directly from a Mod module,
without the writing of an explicit interface description file.
Argument checking comes for free and common
arguments are unloaded automatically.
For example, suppose the following needs to be translated to C:
# File math.tcl
package require Mod
namespace eval ::app::math {
Mod export
proc add {i j} {#TYPES: . Double Double
# Add two doubles together.
return [expr {$i+$j}]
}
proc sub {i j} {#TYPES: . Double Double
# Subtract two doubles.
return [expr {$i-$j}]
}
}
The C extension can be generated thus:
capi math.tcl
gcc -shared -o libappmath.so math.c
This generates the output file math.c which can then
be compiled and loaded into wize.
2. Code Body
In order to be useful math.c must be edited to provide
required code bodies. Unfortunately, all changes
will be lost upon regeneration.
Alternatively, code bodies can be provided via
an array input file. Thus
for the above example the input file might be:
# "File main.inc"
::app::math::add {
Tcl_SetObjResult(interp, Tcl_NewDoubleObj(arg_i + arg_j));
}
::app::math::sub {
Tcl_SetObjResult(interp, Tcl_NewDoubleObj(arg_i - arg_j));
}
body {
/* Code for body */
}
lib {
/* Code for the library Init section. */
}
delete {
/* Code for delete. */
}
vars {
/* Custom vars for CmdEntry. */
int cnt;
}
and invoked as:
capi math.tcl -impl math.inc
3. Using It
The loaded library will return the namespace.
This can be queried thus:
set ns [load ./libappmath.so]
foreach i [info commands ${ns}::*] {
puts "$i [extern $i]"
}
puts [::app::math::add 9 8]
which when run outputs
::app::math::add {i j} {. Double Double} I {Add two doubles together.}
::app::math::sub {i j} {. Double Double} I {Subtract two doubles.}
17
4. Warnings
A major advantage of using CAPI is that code using
it can be validated, eg.
# foo.tcl
load ./libappmath.so
proc Foo {} {
return [app::math add 8 9 9]
}
proc Bar {} {
return [app::math add x 9]
}
When run this outputs:
% wize -Wall foo.tcl
/tmp/foo.tcl:5: warning: too many args, expected parameters
{i j} for "app::math add 8 9 9" in proc [::Foo] <args,30>.
/tmp/foo.tcl:9: warning: for argument #1 "i", the value "x"
does not match type <Double> for "app::math add x 9" in
proc [::Bar] <types,4>.
5. Options
Following are the options for the capi command.
| Option | Default | Description |
| -impl | | Implementation file |
| -iname | | Name to use for XXX_Init |
| -ns | | Namespace to output code for |
| -out | | Output file |
| -wiz | True | Use wize typechecking api |
© 2008 Peter MacDonald