Tclには、Tcllibという100% Pure Tclで記述された拡張パッケージがあります。
Tclで良く使われる便利なプロシジャをパッケージ化したものです。
Tcllibは、TclでTcl拡張パッケージを作成するための良いお手本となるでしょう。
# # cat file ... # proc cat {args} { set out {} foreach file $args { if {[catch {open $file r} fd]} { error "No such file or directory" } while {![eof $fd]} { if {[gets $fd line] < 0} { break } append out $line "\n" } close $fd } return $out } # # head file ?number? # proc head {file {num 10}} { if {[catch {open $file r} fd]} { error "No such file or directory" } set out {} set count 0 while {![eof $fd]} { if {[gets $fd line] < 0} { break } append out $line "\n" incr count if {$count == $num} { break } } close $fd return $out } |
package require Tcl 8.0 package provide mylib 1.0 |
package requireコマンドは、このパッケージを動作させるのに必要な
パッケージを記述します。この例では、Tcl8.0以上が必要となります。
package provideコマンドは、パッケージ名とバージョンを定義します。
namespace eval ::mylib { namespace export * } |
namespace exportコマンドは、すべてのプロシジャを外部に公開します。
catとheadプロシジャは、namespaceで囲うために修正します。
# # cat file ... # proc ::mylib::cat {args} { set out {} foreach file $args { if {[catch {open $file r} fd]} { error "No such file or directory" } while {![eof $fd]} { if {[gets $fd line] < 0} { break } append out $line "\n" } close $fd } return $out } # # head file ?number? # proc ::mylib::head {file {num 10}} { if {[catch {open $file r} fd]} { error "No such file or directory" } set out {} set count 0 while {![eof $fd]} { if {[gets $fd line] < 0} { break } append out $line "\n" incr count if {$count == $num} { break } } close $fd return $out } |
tclshまたはwishでmylib.tclの場所に移動してpkg_mkIndexコマンドを実行します。
cd mylib pkg_mkIndex . mylib.tcl |
mylib.tclと同じディレクトリにpkgIndex.tclが生成されます。
# Tcl package index file, version 1.1 # This file is generated by the "pkg_mkIndex" command # and sourced either when an application starts up or # by a "package unknown" script. It invokes the # "package ifneeded" command to set up package-related # information so that packages will be loaded automatically # in response to "package require" commands. When this # script is sourced, the variable $dir must contain the # full path name of this file's directory. package ifneeded mylib 1.0 [list source [file join $dir mylib.tcl]] |
これでmylibパッケージは完成です。
もし、何かの事情でシステムにインストールできない場合は、
auto_path変数に mylib1.0 のあるディレクトリを追加することで対処できます。
lappend auto_path {d:/work/mylib1.0} |
これでmylibパッケージのインストールは完了です。
package require mylib 1.0 ::mylib::cat foo.txt bar.txt ::mylib::head foo.txt 5 namespace import mylib::* cat foo.txt bar.txt head foo.txt 5 |
TclでTcl拡張を作成するのは、意外と簡単でしたね。