Tk」タグアーカイブ

Tcl/Tkのいいところ

半年くらい前まではC#でGUIアプリケーションを作っていたけど、ここ数ヶ月は主にTcl/Tkを使っている。僕がTcl/Tkを使っている理由は、最初にまともなプログラムを書いたのがTcl/Tkからだったからだ。それ以外に必然的な理由はない。以前はプログラマを名乗るのならば、C/C++/Javaあたりは最低やっておかねばという強迫観念にとらわれていた自分だが、最近C#をやって静的型付言語の雰囲気をかじったことで、まあ、必要になったらやったらいいんじゃないかなくらいに思えてきた。

シェアの大きい言語をほとんど使いこなすことなく、Tcl/TkやRubyといったどちらかというとマイナーな言語ばかり使ってきた僕が、Tcl/Tkに客観的な評価を与えられるとは思わないが、5年間というプログラマー生活を共に過ごしてきたこの言語について、実用的観点でよいと思うことを挙げておきたいと思う。

I/Oの抽象化

ファイル、ソケット通信、シリアル通信などがチャネルというハンドルに対する共通のコマンドで操作できる。さらに、VFS(仮想ファイルシステム)といって、たとえばZIPファイルやFTPを普通のディレクトリと同じコマンドで扱えたりする。

wish.exeって便利

Tkアプリケーションで、console showとか書いとくと、アプリケーションを起動したときにシェルウィンドウが開く。ここからなんでもできてしまう。アプリケーションを走らせたまま書き換えることができる。Rubyでもできるけど、インタラクティブなシェルってコマンドライン上で動くirbしかないよね。Ruby/Tkでイベントループ走らせちゃったらもう何もできないし。

マニュアルが読みやすい

MSDNみたいな非人間的な解説じゃない。コマンドのカテゴリ分けが適切で、ひとつひとつのコマンドやオプションに必要かつ十分な説明が正確な英語で書かれている。サンプルスクリプトが少ないのが不満だったが、Tcler's Wikiという膨大なナレッジベースを参照すればいろいろ見つかる。

実用的なライブラリが豊富

およそライブラリというものには言語の機能を組み合わせて複雑な機能を実現してくれるものと、言語ではできないことを可能にしてくれるものがある。前者のバリエーションの豊富さは言語の力を示すものだ。後者は逆かもしれないが、インタープリタ言語には必要なものだ。そしてTclはどちらの種類のライブラリも本当にたくさん揃っていると思う。Perl,PHP,Rubyみたいなパッケージシステムでteapotレポジトリというのがでてきたので、そのうち実用的になっていくことだろう。Windows向けに、ActiveXコントロールをTkに埋め込むライブラリ、COMインターフェース、Win32APIのラッパーライブラリ、DLLのエクスポート関数を利用するライブラリも存在する。

デプロイが簡単

ActiveStateのTclDevKitを使えば、Tclインタープリタ、ライブラリ、ソースコード、フォント、画像など、すべてを単一の実行ファイルに固めて配布でき、ソースコードの隠蔽もできる。僕は複数のファイルからなる合計2万行程度のスクリプトと、ロゴなどの画像、十数種類のパッケージなどを単一ファイルにラップしているが、せいぜい6MB程度にしかならない。.NET Framework 4 client profileはダウンロードするだけで41MBもある。展開したらもっと大きくなるだろう。仕組みはよく分からないが、英語版WindowsXPに日本語フォントがなくてソースコードのコメントが文字化けしていたときも、コンパイルしたTcl/TkのGUIには日本語が表示できていた。

え、これだけ?とか、どれも言語の機能じゃないんですけど、とつっこまれそうなものばかりだな。。。来年あたり8.6が出るみたいだけど、こいつはかなり進化しているらしいですよ。lambda, coroutineに期待。最近は何でも屋さんの傾向は薄れつつあり、言語自体の近代化が進んでいるように思う。JimというTclのアナザー実装はガベージコレクタを持っているらしい。

実はここでは目をつむった悪いところもたくさんあるんですけど、デプロイがここまで簡単なスクリプト言語ってほかに知らないなあ。あと、目が悪いせいか、美しいとか言われてるRubyのソースコードより、Tclのほうが美しく見えてしまうのですよね。

なんか思いついたら追加するかも。

DataGridViewをActiveXコントロールにラップしてTcl/Tkのウィンドウに埋め込む(3)

これまでの経緯
DataGridViewをActiveXコントロールにラップしてTcl/Tkのウィンドウに埋め込む(1)
DataGridViewをActiveXコントロールにラップしてTcl/Tkのウィンドウに埋め込む(2)

去年やってたoptclによるDataGridView埋め込みが、ようやく役に立つときが来た。
しかし、イベントを追加しようとしたところ、いきなり壁にぶち当たってしまった。

新たに定義したイベントにコールバックを登録できない。

続きを読む

DataGridViewをActiveXコントロールにラップしてTcl/Tkのウィンドウに埋め込む(2)

 

前回に引き続き、イベントの定義をやってみました。

DataGridViewのボタンセルが押されたら、そのセルの行・列番号を引数にして、Tclのプロシージャをコールバックするということがしたい。

ソリューション一式: SimpleDgv.zip

まず、メソッドと別にインターフェースを用意して、InterfaceTypeをComInterfaceType.InterfaceIsIDispatchにします。

[Guid("1AE7D7D7-02EF-4d70-B7F5-71CE046FAEA9"), ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface ISimpleDgvDispatch
{
    void ButtonClick(int col, int row);
}

そして、クラスの属性にComSourceInterfaces(“ISimpleDgvDispatch”)を追加し、クラスにButtonClickイベントを定義します。

[Guid("29E1BC35-88D3-47f0-997D-B889CA25E135"), ComVisible(true), ClassInterface(ClassInterfaceType.None), ComSourceInterfaces(typeof(ISimpleDgvDispatch))]
public partial class SimpleDgv : UserControl, ISimpleDgvInteface
{
    public delegate void ButtonClickDelegate(int col, int row);
    public event ButtonClickDelegate ButtonClick;

    protected void OnButtonClick(int col, int row)
    {
        if (ButtonClick != null)
        {
            ButtonClick(col, row);
        }
    }
}

ビルドするとCOMとして公開されました。

Tcl側のコード

proc ButtonClick {col row} {
    tk_messageBox -type ok -message "Callback Col=$col, Row=$row"
}
optcl::bind $dgvObj ButtonClick ButtonClick

 

さあ、どうでしょう?

エラー全文

イベントを実行したC#側で例外が発生しました。例外テキストからはSystem.RuntimeType.InvokeDispMethodに渡されるcultureが不明なものであったということだろうと解釈できますが、だからといってどうすればよいというのでしょう?

DISP_E_UNKNOWNLCIDとはなんぞや?ググっても文字通りの説明しか出てきません。

AssemblyInfo.csでCultureInfoを指定したりもしてみたが、何も変わらない。

これで丸1日試行錯誤したものの、全く原因も解決法も分からず途方にくれました。

どうしよう。引っ込みがつかない。


2009/9/8 -- 追記: 成功

.Net Framework フォーラムで質問したらjzkeyさんが回答をくれました。

http://social.msdn.microsoft.com/Forums/ja-JP/netfxgeneralja/thread/46e0c5a2-0a89-472e-b4d6-0cd7399e1300

動くようになったoptclのバイナリとソースを置いておきます。

http://yyamasak.drivehq.com/devel/src/tcl/lib/optcl3010t-bin.zip
http://yyamasak.drivehq.com/devel/src/tcl/lib/optcl3010t-src.zip

optclがビルドできるようになったので、とりあえずBase64でのやり取りで妥協したマルチバイト引数の件も調べれば何とかなるかもしれないという希望が出てきました。