Ruby win32ole 拡張モジュール覚え書き(4)

Win32OLE 製作過程の目次へ

extconf.rb の作成

win32ole拡張モジュールをコンパイル・リンクするためには ole32.lib,oleaut32.lib,uuid.lib の3つのライブラリが必要でした. have_libraryをextconf.rbに追加すれば良いのですが, have_libraryの第二引数で指定する適当な関数を見つけることが できませんでした. (いい加減で根気のない私は,すぐに探すことをあきらめました.)

have_library の第二引数で指定する関数は

という条件を満足する必要があります.

結局,私のいい加減な性格により,全部 OleUninitializeを使って

have_library("ole32", "OleUninitialize")
have_library("oleaut32", "OleUninitialize")
have_library("uuid", "OleUninitialize")
create_makefile("win32ole")

と逃げることにしたのでした.

(第二引数に指定する関数は,引数をもたない関数であれば 何でもよかったのでアルファベット順で関数を捜しました. abort が一番最初に引っかかってきましたが, 何となく縁起が悪いような気がしたので, 採用しませんでした.)


method_missing の利用

何度もデバッグを繰り返した後,なんとかこんな Ruby のコードは 動くようになりました.
ap = WIN32OLE.new('Excel.Application')
ap['visible'] = true
ap.invoke('Workbooks').invoke('Add')
「ap.invoke('Workbooks').invoke('Add')」は格好悪いです. 「ap.Workbooks.Add」という風にスマートに書きたいものです. すぐには良い方法を思い付きませんでした. Ruby のメーリングリストで質問しようか とも考えましたが,あるとき method_missing を使えるかも知れないと考えました.

上の例でいえば,"ap" は WIN32OLEオブジェクトで, 定義されているメソッドは "invoke","[]","[]=" の3つだけです. "ap"で method_missingを定義しておけば "ap.Workbooks" とやると "Workbooks" メソッドがないため method_missing が実行されるはずです. method_missing 内で,invokeを起動してやればうまくいくのではないかと 考えました. method_missingを C言語ではどう実装すれば良いのかよくわからなかったので Rubyのスクリプトで method_missingを定義することにしました.

class WIN32OLE
  def method_missing(cmdid, *arg)
    invoke(cmd, *arg)
  end
end
結果は,期待通りです.ap.Workbooks.Add が動くようになりました.

目標達成

excel1.pl と excel2.pl を Ruby のスクリプトに移植して稼動確認してみました. 見事に動いてくれます.感動しました. 全く実用性はありませんが,グラフが回るサンプルが動いたときは さすがにインパクトがありました. (無意味だけどこんなこともできるよというアピール度では excel2.plはすごいサンプルだと思います. 初めて Perlでexcel2.plを動かしたときは 「こんなことまでできるのか.Perlってすごいな」 と私は単純に感動したのを覚えています.)

という訳で,最初のリリースです.
バージョンは,0.0.1 ぐらいから始めておけば,1.0.0 になる頃には まともなソフトになるだろうと考え,0.0.1 に決めました. (かなりいい加減です.)
Windows 環境で動く拡張モジュールということで,tar.gz 形式ではなく cygwin32版 ruby 等と同じ zip 形式で圧縮しました.
そのとき,ftp ができる環境になかったので直接希望者を含め数名の方に メールで送付しました.


早くもバグ

メールで送付した後すぐに,Visual C++ 6.0 でコンパイルした方から バグ報告がありました.パッチもつけてくださっていて助かりました. バグの原因は,私が,Ruby のマクロのALLOCA_NALLOC_N を使い間違えていた という御粗末なものでした.Visual C++ 5.0 でコンパイルしていた 私の環境では幸か不幸か一度もエラーが発生していませんでした.

バグ報告がすぐにあり,パッチまでついてくるというのは オープンソースの強みかなあと実感できたのはこの時です.


早くも要望

「ap['Visible'] = true と書くのは面倒なので ap.Visible = true と書けないでしょうか?」 という要望がありました.

実は,私もこれはできないかなと思って,その要望が出る前から いろいろやってましたがどういう訳かうまくいってなかったのでした. 結局,method_missing を変更して ap.visible = true という書き方はできるようしました.


改めてリリース

バグ1件を修正し,要望1件に対応したものをバージョン0.0.1として, 改めてリリースしました.

Win32OLE 製作過程の目次へ