Tcl/Tk 入門

他のプログラムとの連携

最終更新: [2006/06/15]
Copyright

Tcl による双方向入出力

Tcl による双方向入出力の例です.ソケットなどを持ち出さなくてもファイル入 出力で実現可能のようです.ただ,両方での出力バッファのフラッシングという のが重要で,これを忘れると処理が止まってしまいます.

#このような処理向きの Expect という拡張 Tcl もあるそうです.参考まで.

下に示すのは完全に動作するバージョンです.無限ループするので,Ctrl-c を 入力して適当に止める必要があります.C 側での出力に "\n" を付けないように して下さい.これを行なうと,tk 側での gets を 2 度処理する必要が出てきま す.

[Tcl 側]
#!/usr/local/bin/tclsh

set fid [open "| ./foo" "r+"]  ;# プログラム foo を r+/w+ モードで起動

puts  $fid "tcl:"              ;# 相手プログラムへの初期値の出力
flush $fid                     ;# バッファのフラッシュ(重要)

while {[gets  $fid str]>=0} {  ;# 読み込み
    puts       "tcl:$str"      ;# 画面への出力
    puts  $fid "tcl:$str"      ;# 相手プログラムへの初期値の出力
    flush $fid                 ;# バッファのフラッシュ(重要)
}

[C 側 (プログラム foo となる側)]
#include 

#define STR_NUM 512

int main(int argc, char **argv)
{
    char str[STR_NUM];

    while (!feof(stdin)) {
	fgets(str, STR_NUM, stdin);
	printf("C:%s", str);
	fflush(stdout);
    }
}


パラメータの受渡しの例

$comname に連携処理したい外部起動コマンドの名前を入れる.Tcl 側から逐次 このコマンドを起動しパラメータを与えて動作させる.ここでは3つの 変数 $var_a, $var_b, $var_c の値を起動コマンドへ渡すものとする."#end" を終端文字列として設定して,呼び出される側ではこれを見つけるとデータの読 み込み処理を修了する.

[Tcl 側 (呼び出し側)]
    set f [open "| $comname" r+]

    ########################################
    # Parameter Output
    puts $f "\$var_a=$var_a;"
    puts $f "\$var_b=$var_b;"
    puts $f "\$var_c=$var_c;"
    puts $f "#end"
    flush $f
    
    ########################################
    # Data Read
    while {[gets $f data]>=0} {
      ...

[C 側 (呼び出され側)]
#define STRNUM 512
char str[STRNUM];
int var_a, var_b, var_c;

while (!feof(stdin)) {
    fgets(str, STRNUM, stdin);
    if (strncmp_cnt("$var_a=", str, &n)==0) {
	var_a=atoi(&str[n]);
    } else if (strncmp_cnt("$var_b=", str, &n)==0) {
	var_a=atoi(&str[n]);
    } else if (strncmp_cnt("$var_c=", str, &n)==0) {
	var_a=atoi(&str[n]);
    } else if (strncmp_cnt("#end", str, &n)==0) {
	break;
    } else {
	fprintf(stderr, "Unexpected variable specified.\n");
    }
}

この C 側の処理をもし Perl で書くと次のようにとても簡単になる.

[Perl 側 (呼び出され側)]
# パラメータを読み込んで評価
$line="";
while (<>) {
    last if /^#end/;
    $line.=$_;
}
eval($line);


|| Tcl/Tk 入門||

Mail-to: oshiro@mibai.tec.u-ryukyu.ac.jp