CAPI /
CAPI
Search:  


Table Of Contents (show)

  1. 1. CAPI
  2. 2. Code Body
  3. 3. Using It
  4. 4. Warnings
  5. 5. Options

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.

OptionDefaultDescription
-impl Implementation file
-iname Name to use for XXX_Init
-ns Namespace to output code for
-out Output file
-wizTrueUse wize typechecking api

© 2008 Peter MacDonald

Page last modified on November 16, 2009, at 06:29 PM