Extern Loading
Following is an example of multi-level loading of
a module. We start with the following module:
# File "math.tcl"
package require Mod
namespace eval ::myapp::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}]
}
}
whose header file is:
# File "math.htcl"
package require Mod
namespace eval ::myapp::math {
Mod export
extern add {i j} {. Double Double}
extern sub {i j} {. Double Double}
}
math is just one member of the myapp module:
# File "myapp.htcl"
package require Mod
namespace eval ::myapp {
Mod export
extern math {args} {} {D source $dir/math.htcl}
## Could have other sub-modules...
#extern fill {args} {} {D source $dir/fill.htcl}
#extern check {args} {} {D source $dir/check.htcl}
}
This would then be used as follows:
extern ::myapp {args} {} {D source $dir/myapp.htcl}
#...
puts [::myapp math add 9 10]
Compiled Extension
A module can easily be turned into a compiled
extension. First define a C bodies include file:
# "File math.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));
}
Then run CAPI to generate main.c and compile:
% capi math.tcl -impl math.inc
Generated: Myappmath math.c
% cc -shared -o libMyappmath.so math.c
Now tcl::loadextern will automatically
load the shared library. If not available we
fall back to the Tcl implementation.
NOTE: the library name is by default formed from
the namespace using:
string totitle [string map {:: {}} $namespace]
© 2008 Peter MacDonald