Gauche で OLE オートメーションを利用するライブラリの作成を先日から取り組んでいますが、少し進展があったので一旦リリースすることにしました。
http://saito.s4.xrea.com/software/Gauche-OLE-0.5.tar.gz
変更や追加は以下の通りです。
メソッド名とプロパティ名をシンボルで表現
従来はメソッド名やプロパティ名は文字列で与えていました。 それをシンボルで表現するようにしました。
例えば object というオブジェクトの method というメソッドを起動したい場合は以下のようになります。
(ole-invoke object 'method)
object-apply を定義してあるので以下のように呼出してもよいです。
(object 'method)
シンボルで表現するようにしたのは将来的にメソッド名の探索をキャッシュする機構を導入することを見据えた変更です。 文字列の比較よりシンボルの比較の方が高速であるため、どのようなコンテナにキャッシュすることにしたとしても有利になるはずです。 ただ、オブジェクトが持っているメソッドやプロパティは不変であるとは限らないということもドキュメントには書いてあるので、今のところキャッシュの導入を積極的にやろうとは考えていません。
また、 Gauche のオブジェクトシステムにおけるスロット名の表現にもシンボルが用いられていることもあって、より Gauche に馴染む表現であると考えています。
プロパティへのアクセス
オートメーション・オブジェクトのプロパティへアクセスするために ole-ref という手続きを用意しています。 従来は、メソッドの呼出しの ole-invoke とプロパティの参照の ole-ref は明確に区別していましたが、 ole-invoke でもプロパティへのアクセスが出来るようになりました。
オートメーションの規約はメソッド呼出しかプロパティの参照か曖昧な場合を解決することを要求しています。 マイクロソフトのサイトにあるドキュメントでは、 Visual Basic の構文の曖昧さに対処するための規約であることが述べられており、あるべきレイヤで解決していないひどい仕組だと思うのですが、オートメーションの側で解決可能なら呼出し側で区別するのは余計な制限だという判断です。
http://msdn.microsoft.com/ja-jp/library/cc482689.aspx
また、後述のメソッドチェイン構文を使ってみたところ、区別がない方が簡素で良いと思えたという理由もあります。
メソッドチェイン構文
JavaScript や Ruby ではメソッドの呼出しを重ねていくメソッドチェインと呼ばれる記法が多用されます。 メソッドが返したオブジェクトのメソッドを呼出すという連鎖を表現するもので、例えば以下のようなものです。
obj.hoge().fuga().piyo();
同様に、連鎖を表現する構文を用意しました。
(& obj 'hoge & 'huga & 'piyo)
Gauche にある $ という構文の結合の向きを逆にしたものと考えてもいいでしょう。 メソッド呼出しとプロパティの参照を区別して記号を使い分けるという案も考えたのですが、あくまでも $ と同じように括弧の連鎖のかわりであって、意味に踏み込まないという判断をしました。
そうなると、上述のようにメソッド呼出しとプロパティの参照を曖昧にする必要が生じます。 ひどい規約だと思ったものを活用してしまうことに微妙な気持があったのですが、実際に使ってみるとそれなりに使い勝手がよいので、やってみなきゃわからないものだと思いました。
メソッド名/プロパティ名の一覧
オブジェクトが持っているメソッドやプロパティの名前一覧を見ることが出来るようになりました。 ole-methods という手続きを通すと名前と数値を組にした連想リストが返ってきます。 数値の意味は VARFLAGS の値そのままです。
http://msdn.microsoft.com/en-us/library/windows/desktop/ms221426(v=vs.85).aspx
現時点では、この連想リストはユーザに対するドキュメントであると想定しています。 この連想リストを利用するようなプログラムを書くことはお勧めできません。 というより試行錯誤中なのでどの機能も完全にこれでいこうと確定しているわけではないのですが。
コレクション型への統合
オートメーションオブジェクトが IEnumVariant インターフェイスをそなえている場合には Gauche 上でコレクションとして扱えるようにしました。
ただし、現状では上手く統合できていません。 オートメーションオブジェクトは Gauche 上では全て等しく <ole> クラスのオブジェクトであって、 IEnumVariant インターフェイスを持っているかどうかを型で区別しません。 コレクションとして扱えるようにするために <ole> クラスは <collection> を継承しているのですが、もちろんコレクションでないような <ole> オブジェクトも存在する (というよりほとんどそう) なので、問答無用で <collection> を継承しているというのは問題があります。 しかし、 COM としての継承関係を Gauche で表すのも困難で、どう表現したものか考えがまとまっていません。
型変換
VARIANT 型の配列、つまり vt メンバの値が VT_VARIANT|VT_ARRAY であるような値が返ってきたときに Gauche の array 型に変換するようにしました。 多次元だったり、オリジンをどうとでも設定できるという自由さを持つ Gauche の型は array しかなかったからです。
OLE オートメーション (COM) で使われる型の種類はたくさんあり、全てを網羅するのは手間がかかりそうです。 とりあえず手元にあるいくつかのアプリケーションソフトで使われている型から手をつけている状態です。 こういうときこそ CiSE を活用するべきなのかもしれませんが、それはそれでわかりやすいドキュメントもなく慣れないとなかなか使い熟すのは難しそうです。
Document ID: 237a202475a0b9cb97a56550f2b78e35