Recent Changes - Search:

Extern

(:toc:)

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.

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]]

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.

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}

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

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.

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.

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.

Edit - History - Print - Recent Changes - Search
Page last modified on May 18, 2010, at 06:15 PM