こんにちは、高木です。
昨年10月に「これからの計画」ということで、当サイトの連載計画について書いたことがあります。その中で次のように書きました。
さしあたってはPHPやTcl/Tkの話題を考えています
PHPについてはいったん連載を終了しましたので、次はTcl/Tkの話題になります。具体的には、C++からTcl/Tk、とくにGUIツールキットであるTkを使う方法について書いていくことにします。
実はこの話題は以前にも何度か書いたことがあります。ちょっと時間が経ってしまいましたので、今回は基本的なことからおさらいしていきましょう。
今回の連載では、C++からライブラリーとしてTkを呼び出します。TkというのはTool Kitの意味で、本来はプログラミング言語Tclのライブラリーです。簡単にGUIが作れるすぐれたライブラリーですので、PerlやPythonやRubyなどにバインディングされています。現在、Tkに付いて調べようとすると、Tcl/TkよりPythonバインディングであるTkinterの情報の方が多く集まるぐらいです。
Tkが登場したのは1991年ですので、Windows向けのGUIフレームワークであるMFCが登場するより前になります。実に30年以上の歴史があり、古いですが非常に枯れたライブラリーだといえます。そんなTkですが、現在でもメンテナンスされ続けていて、現時点(2022年1月8日)での最新版は2021年11月5日にリリースされたバージョン8.6.12です。
それではTcl/Tkを使った簡単なプログラムを書いてみます。
0 1 2 |
pack [button .b -text exit -command exit] |
これを実行すると、小さなウィンドウの中に「exit」と書かれたボタンがひとつだけ配置されます。このボタンをクリックするとウィンドウが閉じ、プログラムは終了します。
今度はこのプログラムをC++から呼び出してみましょう。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <tk.h> int main(int argc, char* argv[]) { // 実行ファイルのパスを教える。 Tcl_FindExecutable(argv[0]); // インタープリターを作成して初期化 auto interp = Tcl_CreateInterp(); Tcl_Init(interp); Tk_Init(interp); // スクリプトを実行 Tcl_Eval(interp, "pack [button .b -text exit -command exit]"); // イベント処理用のループを実行 Tk_MainLoop(); // 終了 Tcl_Exit(0); } |
これは本当に最小限のプログラムです。流れを把握しやすくするためにエラーチェックも省略しています。たったこれだけのプログラムでGUIのプログラミングができるのですが、できればこういう定型的な内容はライブラリー化してしまって、より簡単にGUIアプリケーションを作成できるようにしたいものです。C++なら適切なラッパーライブラリーを作成することで実現できそうです。
ところで、Tcl/Tkは1990年代の半ばまでは非常に人気があったのですが、その後人気が衰えていったようです。理由としては、ルック&フィールがいつまでもMotif風で古くさかったこと、(当時の)新しいGUIでは当たり前に使われていたような部品がなかったことなどが挙げられます。しかし、現在ではその多くは解消されています。
現在は新しく登場するUI向けのライブラリーやフレームワークはWebが中心です。しかし、ちょっとしたGUIツールを作りたいだけなのにWebサーバーが必要になるのは便利が悪すぎます。そんな「ちょっとした」GUIアプリケーションの開発には現在でもTcl/Tkは便利だと考えています。
先ほども書いたように、現在ではTkについて調べようとするとPythonバインディングであるTkinterに関する情報の方が多く集まります。それなら、Tcl/TkではなくTkinterをC++から呼び出せばいいという考え方もあります。Boost.Pythonを使えばC++からPythonを呼び出すことはできますから。
ただ、Tkinterを使うには、Pythonの処理系はもちろん、Tcl/Tkもインストールしなければなりません。Tkを使いたいだけであれば回りくどいので、C++から直接Tcl/Tkを呼び出す方が構造的にシンプルです。また、本格的に使い出すと、TclやTkのC言語APIを呼び出したいことも普通に出てきます。そんなときにはPython層が邪魔になってきます。
今回は初回ですので簡単な紹介だけにとどめておくことにします。次回からは本格的にいろんなことに挑戦していきたいと思います。