第13回はTcl/Tkを使ってみましょう。Tcl/Tkは、スクリプト言語のTclと、そのGUI拡張であるTkとによって構成されています。まずはTclのみを使ったHello Worldを作成し、その後Tcl/TkのGUIのHello Worldを作成していきます。

Tclのputsを使う方法

リスト1は、Tclのputsを使ったHello Worldです。このようにTclスクリプトでは、インタプリタとしてtclshを使います。putsでは、改行は自動的に付加されます。Tclの文字列は、{ }またはダブルクォートで囲みます。ダブルクォートの場合は\nなどのエスケープ文字が解釈されますが、{ }の場合はそのままの文字列と解釈されます。

リスト1 Tclのputsを使う(tcl_puts)

#!/usr/bin/tclsh       ← Tclのインタプリタであるtclshを指定

puts {Hello World}     ← putsで文字列を出力(改行は自動)

Tclのスクリプトは、ほかのスクリプトと同様、実行例1のように実行属性を付ければ実行できます。

実行例1 Tclスクリプトの実行

$ chmod +x tcl_puts        ← Tclスクリプトに実行属性を付ける
$ ./tcl_puts               ← Tclスクリプトを実行
Hello World                ← 確かにHello Worldと表示される
$                          ← シェルのプロンプトに戻る

putsで改行しない方法

putsは改行コードを付加しますが、-nonewlineオプションを付けると、改行の付加を抑制できます。そこで、リスト2のように、自分で改行コードを記述する方法も考えられます。ここでは文字列はダブルクォートで囲む必要があります。

リスト2 putsで改行しない方法(tcl_puts2)

#!/usr/bin/tclsh

puts -nonewline "Hello World\n"   ← putsに任せず、自分で改行コードを記述する

Tclのformatを使う方法

Tclでは、printf形式の書式指定はformatを使って行います(リスト3)。formatは、sprintfに相当する動作を行い、結果の文字列を出力するため、これを[ ]で取り込んで、putsなどの引数として利用します。ここでは、format側で改行を付加し、putsの方には-nonewlineオプションを付けています。

リスト3 formatを使う方法(tcl_format)

#!/usr/bin/tclsh

puts -nonewline [format "%s\n" {Hello World}]   ← formatで書式指定しputsで出力

OSのコマンドを実行する方法

TclからOSのコマンドを呼び出すには、リスト4のようにexecを使います。このexecは、シェルスクリプトのexecとは違って、OSのコマンドを呼び出したあとはTclに制御が戻ってきます。また、execの出力を標準出力に出力するには、明示的に「>@ stdout」というリダイレクトを行う必要があります。

リスト4 OSのコマンドを実行する方法(tcl_exec)

#!/usr/bin/tclsh

exec echo {Hello World} >@ stdout    ← OS上のechoコマンドを呼び出す

C言語からTclライブラリを使う

Tclのライブラリは、C言語から呼び出して使うこともできます。標準出力に文字列を出力するには、リスト5のように、必要な前処理のあと、Tcl_Write()関数を使って出力します。

リスト5 C言語からTclライブラリを使う(tcl_c_write.c)

#include <tcl.h>                   ← Tclのヘッダが必要

int
main()
{
  Tcl_Interp *interp;              ← Tclのインタプリタへのポインタ
  Tcl_Channel channel;             ← Tclの入出力チャンネル

  interp = Tcl_CreateInterp();              ← インタプリタを作成
  channel = Tcl_GetStdChannel(TCL_STDOUT);  ← 標準出力のチャンネルを取得
  Tcl_Write(channel, "Hello World\n", 12);  ← 標準出力に文字列を出力

  return 0;
}

このプログラムはTclのライブラリとリンクするため、実行例1のように「-ltcl」を追加してコンパイルします。

実行例1 Tclライブラリを使ったプログラムのコンパイル

$ gcc -O2 -o tcl_c_write tcl_c_write.c -ltcl   ← 「-ltcl」を追加してコンパイル

C言語からTclスクリプトを実行

Tclスクリプトの文字列を解釈して実行する、Tcl_Eval()という関数があります。このTcl_Eval()を呼び出すことによって、C言語からTclスクリプトを実行することも可能です(リスト6)。ここでは、TclスクリプトがC言語のソース中に文字列として埋め込まれています。なお、このプログラムも前項の実行例1と同様に、「-ltcl」を追加してコンパイルします。

リスト6 C言語からTclスクリプトを実行(tcl_c_eval.c)

#include <tcl.h>                   ← Tclのヘッダが必要

int
main()
{
  Tcl_Interp *interp;              ← Tclのインタプリタへのポインタ

  interp = Tcl_CreateInterp();     ← インタプリタを作成
  Tcl_Init(interp);                ← Tclを初期化

  Tcl_Eval(                        ← Tcl_Eval()でTclスクリプトを実行
    interp,                        ← インタプリタを指定
    "puts {Hello World}\n"         ← Tclスクリプトの文字列を引数とする
  );
  return 0;
}

Tcl/TkのHello World

次は、TclにTkを加えた、Tcl/TkのGUIのプログラムです。 Tcl/Tkのスクリプトでは、インタプリタとして、tclshの代わりにwishを用います。Hello Worldのプログラムは、リスト7のようにlabelを使って記述します。実行すると図1のウィンドウが表示されます。

リスト7 Tcl/TkのHello World(tk_label)

#!/usr/bin/wish                                        ← インタプリタはwish

label .hello -text {Hello World} -width 22 -height 5   ← ラベルを作成
pack .hello                                            ← ラベルを配置

図1 Tcl/TkのHello World

C言語からwishスクリプトを実行

Tcl/Tkのwish用スクリプトも、C言語からTcl_Eval()を呼び出すことによって実行することができます(リスト8)。ただし、Tcl単独のスクリプトを実行する場合とは違って、Tk_Init()とTk_MainLoop()の呼び出しが必要です。なお、Tcl_Eval()の引数のTcl/Tkのスクリプト文字列は、2行に分けて記述していますが、コンパイル時には1つの文字列として連結されることに注意してください。

リスト8 C言語からwishスクリプトを実行(tk_c_label.c)

#include <tcl.h>                   ← Tclのヘッダが必要
#include <tk.h>                    ← Tkのヘッダが必要

int
main()
{
  Tcl_Interp *interp;              ← Tclのインタプリタへのポインタ

  interp = Tcl_CreateInterp();     ← インタプリタを作成
  Tcl_Init(interp);                ← Tclを初期化
  Tk_Init(interp);                 ← Tkを初期化

  Tcl_Eval(                        ← Tcl_Eval()でTcl/Tkのスクリプトを実行
    interp,                        ← インタプリタを指定
    "label .hello -text {Hello World} -width 22 -height 5\n"
    "pack .hello\n"                ←↑ Tcl/Tkのスクリプト文字列(2行で1つの引数)
  );

  Tk_MainLoop();                   ← メインループを実行
  return 0;
}

このプログラムは、TkとTclのライブラリとリンクするため、実行例2のように「-ltk -ltcl」を追加してコンパイルします。実行時の画面は、前掲の図1と同じです。

実行例2 Tcl/Tkライブラリを使ったプログラムのコンパイル

$ gcc -O2 -o tk_c_label tk_c_label.c -ltk -ltcl  ← 「-ltk -ltcl」を追加