Ruby の作者の まつもとゆきひろさんから
「英語のドキュメントつけてね」
「method_missing の実装がRubyスクリプトになってるけど, 拡張モジュールは,全部 C で書くのが私の好み」と言われました. ・・・宿題を出された生徒の気分です.^^;
世界を相手にしている Ruby には英語のドキュメントが必要だというのは 理解できます.素直にできの悪い生徒なりに頑張ることにしました. (英語は苦手です.・・・もっとも日本語も怪しいもんですが.)
method_missing の C による実装は,まつもとさんの好みというだけのようですので, 「そんなん知るか」と反抗しても良かったのですが, まつもとさんの好みとは別の理由で,C で書くことにしました.
C で全部書いておけば,
- RUBYLIB ディレクトリにスクリプトのファイルをコピーする手間が省ける.
- 管理するファイルの数が1つ減る.
- Cのソースとスクリプトの両方をメンテナンスするよりも, Cのソースだけメンテナンスする方が楽.
- 処理が速くなる(かも知れない).
と考えたからです.
じゃあ何故最初から C で書かなかったのか? それは私が,method_missing を C で実装する方法がわからなかったからです.
難しく考えないで,他のメソッドを C で書く場合と同じように書けば良かったのでした. スクリプトで書いた method_missing を素直に,C に置き換えていけば, 実装できたのでわりと簡単でした.スクリプトでメソッドを定義していくのと同じような感覚で 拡張モジュールをCで書けるところが Ruby のすごいところだと思います. (まつもとさんは,そのことも計算して Ruby の設計をしているに違いないと思います.)
WIN32OLE::new メソッドは,新規に OLE オートメーションサーバーを起動します. 起動中の OLE オートメーションサーバーにアクセスする手段がなかったので それを用意することにしました.WIN32OLE::connect メソッドです. 例によって Perl のソースコードを流用して(参考にして),実装しました.
と言う訳で英語のドキュメントを用意し,C言語で全部実装し, 新機能を1つ追加して,バージョン 0.0.2 をリリースしました.
相変わらず,Perl の OLE モジュールを使っている知人に, Ruby にも win32ole 拡張モジュールができたことを伝えたところ
「名前付き引数は使える? 定数は使える?」と質問され,両方とも使えないと答えると知人は小さくガッツポーズをし, 「勝った。」と一言つぶやいたのでした. ・・・こうして私はまたしても知人を Ruby ユーザーにすることに失敗しました.
Excel VBA などでは
'Sheet1 シートの後ろに 2枚シートを追加する. Worksheets.Add(count:=2, after:="Sheet1")というように名前付き引数を使ってメソッドを呼び出すことができます. 名前付き引数の良いところは,
- 省略したい引数は指定しなくても良い.
- 引数の順番を気にしなくても良い.
というところです.
Perl では名前付き引数をハッシュを使って実現しています.
$Worksheets->Add({count=>2, before=>"Sheet1"});Ruby の win32ole でも Perl に倣ってハッシュを使って実現することにしました.
worksheets.add({'count'=>2, 'before'=>"Sheet1"})すべての引数にハッシュを使用できてもそのメリットはあまりないし, その割に実装が面倒だと考えて, 最後の引数にだけハッシュを指定できることにしました.
worksheets.add({'count'=>2, 'before'=>"Sheet1"}) はOK. worksheets.add("Sheet1", {'count'=>2}) もOK. worksheets.add({'count'=>2}, {'before'=>"Sheet1"}) は駄目.
一応,名前付き引数の実装はできていたのですが, C言語レベルでの Ruby のハッシュの扱い方に, ちょっと自信がなかったので質問しました.
回答は
ハッシュの要素を1つずつ取り出して何か処理するには, rb_iterate と rb_each を 組み合わせを使う.
というものでした.
私は,違う関数を使って実装していました. ですが,まつもとさん推奨の実装方法に従っておいた方が, Ruby 本体のバージョンアップにも対応しやすいだろうと考えて rb_iterate と rb_each を使って実装しなおしておくことにしました. (基本方針4)
やっぱり,聞いてみないとわからないもんです.
cygwin32版 Rubyでも, win32ole 拡張モジュールが動いたという非常に嬉しい情報がありました. (わたなべさんに感謝.)
正直言って私は,cygwin32版では,動作させるのが無理ではないかと 思っていました. cygwin32 B19のヘッダーファイルには,Invoke など win32oleで使っている関数の宣言が無かったからです.
lcc-win32 のヘッダーファイルを使って動くようにしたそうです.
Excel が無くても動くサンプルをつけて欲しいという要望がありました.
WSH が使える環境や Internet Explorer Ver 4.0 以降がインストールされている環境だと いろいろサンプルを作れそうです. ですが,結局,中田さん提供の Internet Explorer を使ったサンプルを流用させて頂くことにしました. このサンプルの方がより多くの環境で動作するだろうと考えたからです.
ついでに名前付き引数の例としてもう一つ excel3.rb を追加しました. (結局 Excel を使う私.^^;)
ということで,0.0.3 をめでたくリリースしました. ですが,自分では一度も実用で win32ole を使ったことがないのでした.