1. Extern
An extern is a
function prototype for Tcl, which provides:
- forward declaration of procs, commands and aliases.
- optional type information for the return value and args.
- on-demand code loading support.
The general form of an extern is:
extern NAME ARGLIST ?TYPELIST? ?BIND? ?COMMENT?
The first 2 arguments (NAME and ARGLIST) are
exactly as used in a Tcl proc.eg.
extern ::lib::crypt {str password}
The TYPELIST, if non-empty,
specifies the type of return-values and arguments.
The
BIND, if non-empty,
is a single letter with optional parameters.
It determines the function of the extern.
1.1 Examples
Here are some examples using extern:
extern reverse {str}
extern resets {n} {Int Int}
extern ::incr {varName {amount 1}} {Int var Int} I "Increment a variable"
When an extern specifies type information
it is usable for validating arguments
and command completion.
When an "extern" is used it creates a proc, and
namespace if necessary. Subsequently, an
invocation can perform loading of the code as specified
by the binding
(typically this is handled by [::tcl::loadextern]).
[g[#TYPELIST]]
1.2 TYPELIST
The typelist field of an extern optionally specifies
the data type of the return value and arguments.
Each type element is a string like int or Double
that describes the expected form of the data.
For example, the extern for the [incr] command might be:
extern incr {varName {amount 1}} {Int var Int} I
See Types for more information.
1.3 BIND
A BIND is a single letter,
(followed possibly by options) defining the purpose
of the extern. The binding (if given) must be one of:
- P - Proc definition (the default).
- I - Internal command (ie. non-proc).
- A - Define alias using options.
- E - Eval string, when called.
- D - Eval, like E but if -Wall eval now.
- R - Relay object command.
If no binding is given, it defaults to P.
E/D is an eval. It sets the variable ::dir, and
typically loads code to
replace the extern with a real proc/command.
R is a special case used for nested ensembles.
Its option is
an integer indicating of how many namespace tails to append
(defaults to 0).
Here are some more examples:
extern foo {args} {} {A bar 0 99} "An alias that calls bar"
extern radical {args} {} {E package require Radical}
extern pickle {args} {} {D source $dir/pickle.htcl}
extern ::text::insert {w idx str args} {} R
extern ::text::tag::conf {w tag args} {} {R 1}
1.4 Auto-Generation
An advantage of extern is that it can easily be
generated automatically.
There is no need
to hand-code as you would in C because Tcl
introspection renders this trivial. The
interface component of Mod supports generation of externs,
via Ted, or from the command-line, ie.
wize / Mod/Interface script.tcl > script.htcl
1.5 Ensembles
Ensembles are a new feature in Tcl8.5 which provides a simple way of defining
compound or sub-commands using a namespace. This functionality is
implemented by Mod for versions of Tcl prior to 8.5, to provide backward
compatibility. Ensembles are a welcome addition to tcl, but
their only real issue is that
they require Tcl 8.5. This leads us
to Modules in the next section.
1.6 Module Loading
The following example demonstrates loading a module.
extern ::lib::b64 {args} {} {D source $::dir/b64.htcl}
#...
puts [lib::b64 encode "Some Data"]
Using D instead of E ensures that
when using -Wall, b64.htcl is loaded immediately
so that externs are available and signatures
are checked. When not debugging, the
load is deferred until the first call.
And the header file is:
# File "b64.htcl"
namespace eval ::lib::b64 {
#Mod export
namespace ensemble create
namespace export {[a-z]*}
extern encode {str} {} {E source $::dir/b64.tcl}
extern decode {str} {} {E source $::dir/b64.tcl}
}
Note: extern calls tcl::loadextern which
trys to load the .tcl
or .so/.dll (from current or parent directory).
So the above can be simplified to:
# File "b64.htcl"
namespace eval ::lib::b64 {
#Mod export
namespace ensemble create
namespace export {[a-z]*}
extern encode {str}
extern decode {str}
}
See Loading for a more complex multi-level loading example.
1.7 Advantages and Benefits
extern provides a number
capabilities, including:
- Advanced type checking.
- A layered mechanism for demand loading code.
- Simplified declaration for aliases.
- Introspection for command completion (as implemented in Ted)
- Simplified interfacing/conversion of Tcl to C.
- Relay of object commands for command refactoring.
For a more detailed discussion of motives
behind the creation of extern see Why Extern.
© 2008 Peter MacDonald