昨日 koji さんから、Linux 上の MinGW クロスコンパイラ環境を利用した、C による Tcl/Tk 拡張に関するご質問を、コメントとして頂きました【
コメント】。いい機会ですので、C による Tcl/Tk の拡張の話題を、クロスコンパイルする話題に絡めて、しばらく取り上げていきたいと思います。
最初の話題として、koji さんがコメント欄に掲載したサンプルをベースに、Linux における Tcl/Tk の拡張例を紹介したいと思います。
koji さんが掲載したサンプルは、Tcl のスクリプトを wish に埋め込んだ wish アプリケーションです。Tcl/Tk では、標準で wish (
windowing shell) という Tcl のコマンドシェルが利用できますが、Tcl/Tk の C
API を利用して、標準の wish とは別に、カスタマイズした wish を作成できます。
カスタマイズできることは、koji さんが示したサンプルのように、スクリプトを埋め込んで、wish アプリケーションを即起動できるようにしたり、あるいは Tcl のコマンドを追加、あるいは拡張して、標準の wish にない機能を備えた拡張 wish をビルドすることです。
ここでは koji さんのサンプルコードをベースにして、
kwish という名前の、スクリプトが埋め込まれた拡張 wish をビルドしてみましょう。
コンパイル環境
コンパイル環境は、以下の通り Fedora 8 に収録されている Tcl/Tk のパッケージを使用しています。なお、一般的な gcc の開発環境が整っていることを前提にしています。
Fedora 8 (i386)tcl-8.4.17-1.fc8tcl-devel-8.4.17-1.fc8tk-8.4.17-2.fc8tk-devel-8.4.17-2.fc8プログラム
まず
main 関数を含んだソース
kwish_main.c を示します。このプログラムは、Tcl/Tk のインタープリタを初期化し、Tcl のスクリプトを処理する関数
app_custom を呼び出したあとに、
Tk_MainLoop を実行して GUI のためのイベントループ状態に入ります。
/* kwish_main.c */ #include "kwish.h"
int main (int argc, char *argv[]) { Tcl_Interp *interp;
interp = Tcl_CreateInterp (); Tcl_FindExecutable (argv[0]);
if (Tcl_Init (interp) != TCL_OK) { fprintf (stderr, "FATAL: Tcl initialization error: %s\n", Tcl_GetStringResult (interp)); return EXIT_FAILURE; }
if (Tk_Init (interp) != TCL_OK) { fprintf (stderr, "FATAL: Tk initialization error: %s\n", Tcl_GetStringResult (interp)); return EXIT_FAILURE; }
if (app_custom (interp) != TCL_OK) { printf ("%s\n", "Program End with script error!"); return EXIT_FAILURE; }
Tk_MainLoop ();
return EXIT_SUCCESS; } /* kwish_main.c */ |
次の
kwish_sub.c では、
kwish を起動したときに実行するスクリプトを処理する関数
app_custom を記述しています。koji さんのサンプルでは、定義したスクリプトを
UTF-8 にエンコードしています。これはスクリプトに日本語文字など
ASCII 以外の文字を含み、かつ、(MS Windows のように)システムのエンコーディングが UTF-8 と異なる場合に役に立ちます。今回使用するスクリプトでは関係がありませんが、そのまま残しました。
/* kwish_sub.c */ #include "kwish.h"
int app_custom (Tcl_Interp * interp) { Tcl_DString ds; char script[] = "\n\ wm title . {kwish}\n\ label .1lbl -text {Enter your name (and click OK):}\n\ entry .ent2\n\ button .cmd3 -text OK -command ok_clicked\n\ button .cmd4 -text {Exit this program} -command exit\n\ pack .1lbl -anc w\n\ pack .ent2 -fill x\n\ pack .cmd3 -fill x\n\ pack .cmd4 -fill x\n\ proc ok_clicked {} {\n\ tk_messageBox -message \"[.ent2 get], you are here!\"\n\ }\n\ "; char *script_utf = Tcl_ExternalToUtfDString (NULL, script, -1, &ds);
if (Tcl_Eval (interp, script_utf) != TCL_OK) { fprintf (stderr, "Error: %s\n", Tcl_GetStringResult (interp)); return TCL_ERROR; }
Tcl_DStringFree (&ds);
return TCL_OK; } /* kwish_sub.c */ |
インクルードファイル
kwish.h には、このプログラムで使用するインクルードファイルやプロトタイプ関数宣言をまとめました。
/* kwish.h */ #if !defined(KWISH_H) #define KWISH_H
#include <stdio.h> #include <stdlib.h> #include <tcl.h> #include <tk.h>
extern int app_custom (Tcl_Interp *);
#endif /* KWISH_H */ /* kwish.h */ |
最後に
Makefile を示します。リンクでは意図的に、
-ltcl -ltk として、Tcl/Tk のバージョンに依存しないようにしました。そのため、
tcl-devel と
tk-devel パッケージがビルド時に必要になります。
【注意】本ブログ上では、Makefile におけるコマンド行の先頭部分のタブが表現できないので、コピーして利用する場合はタブ文字に変更してください。# Makefile
CC = gcc RM = rm -f
TARGET = kwish
OBJEXT = .o TARGETEXT =
DEFS = INCLUDE = -I/usr/include CFLAGS = -Wall -O2 $(DEFS) $(INCLUDE) LDFLAGS = -L/usr/lib TK_LIBS = -ltk -ltcl LIBS = $(TK_LIBS) -lX11 -lm
OBJS = \ kwish_main$(OBJEXT) \ kwish_sub$(OBJEXT)
all: kwish$(TARGETEXT)
kwish$(TARGETEXT): $(OBJS) $(CC) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)
.c.$(OBJEXT): $(CC) -c $(CFLAGS) $< -o $@
$(OBJS): kwish.h
clean: $(RM) kwish$(TARGETEXT) $(OBJS) *~
# Makefile |
ビルドと実行
以上のソースファイルと
Makefile を、同じディレクトリ内に保存し、make コマンドで
kwish をビルドします。以下に実行例を示しました。
$ make gcc -Wall -O2 -I/usr/include -c -o kwish_main.o kwish_main.c gcc -Wall -O2 -I/usr/include -c -o kwish_sub.o kwish_sub.c gcc -o kwish kwish_main.o kwish_sub.o -L/usr/lib -ltk -ltcl -lX11 -lm $ ./kwish |
kwish の実行例
このように、簡単に wish にスクリプトを埋め込んだ、拡張 wish をビルドすることができます。次のステップとして、Linux 上の MinGW クロスコンパイル環境下で、同じソースファイルを使って、Winodws 用のバイナリをビルドしてみたいと思います。
wine を利用した Windows 版 kwish の実行例
参考資料
[1]
Tcl Library[2]
Tk Library
2 件のコメント:
解説をありがとうございます。
できれば、windows用クロスコンパイルのMakefileも示していただけるとありがたいです。
koji さん、コメントをありがとうございます。クロスコンパイル環境における Makefile については次回に説明する予定です。暫くお待ちください。
コメントを投稿