【コラム】

Hello Worldコレクション

13 C言語からの拡張も簡単な開発効率の高さがポイント - Tcl/Tk編

    山森丈範  [2008/08/08]

    第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」を追加
    
    関連したタグ

    新着記事

    特設サイトの情報

      求人情報

      人気記事

      一覧

      イチオシ記事

      新着記事

      特別企画

      転職ノウハウ

      あなたの仕事適性診断

      4つの診断で、自分の適性を見つめなおそう!

      Heroes File ~挑戦者たち~

      働くこと・挑戦し続けることへの思いを綴ったインタビュー

      はじめての転職診断

      あなたにピッタリのアドバイスを読むことができます。

      転職Q&A

      転職に必要な情報が収集できます

      スカウト転職する

      企業からアプローチのメッセージが届きます。

      マイナビニュースマガジン