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 が一番最初に引っかかってきましたが, 何となく縁起が悪いような気がしたので, 採用しませんでした.)
何度もデバッグを繰り返した後,なんとかこんな Ruby のコードは 動くようになりました.「ap.invoke('Workbooks').invoke('Add')」は格好悪いです. 「ap.Workbooks.Add」という風にスマートに書きたいものです. すぐには良い方法を思い付きませんでした. Ruby のメーリングリストで質問しようか とも考えましたが,あるとき method_missing を使えるかも知れないと考えました.ap = WIN32OLE.new('Excel.Application') ap['visible'] = true ap.invoke('Workbooks').invoke('Add')上の例でいえば,"ap" は WIN32OLEオブジェクトで, 定義されているメソッドは "invoke","[]","[]=" の3つだけです. "ap"で method_missingを定義しておけば "ap.Workbooks" とやると "Workbooks" メソッドがないため method_missing が実行されるはずです. method_missing 内で,invokeを起動してやればうまくいくのではないかと 考えました. method_missingを C言語ではどう実装すれば良いのかよくわからなかったので Rubyのスクリプトで method_missingを定義することにしました.
結果は,期待通りです.ap.Workbooks.Add が動くようになりました.class WIN32OLE def method_missing(cmdid, *arg) invoke(cmd, *arg) end end
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_N と ALLOC_N を使い間違えていた という御粗末なものでした.Visual C++ 5.0 でコンパイルしていた 私の環境では幸か不幸か一度もエラーが発生していませんでした.バグ報告がすぐにあり,パッチまでついてくるというのは オープンソースの強みかなあと実感できたのはこの時です.
「ap['Visible'] = true と書くのは面倒なので ap.Visible = true と書けないでしょうか?」 という要望がありました.実は,私もこれはできないかなと思って,その要望が出る前から いろいろやってましたがどういう訳かうまくいってなかったのでした. 結局,method_missing を変更して ap.visible = true という書き方はできるようしました.
バグ1件を修正し,要望1件に対応したものをバージョン0.0.1として, 改めてリリースしました.