つらつらと Cygwinの oaidl.hを眺めていました。
ITypeInfo::CreateInstance
とITypeInfo::Invoke
なる関数があることを初めて知りました。
Win32OLEで使えるかも知れないと思って、試行錯誤しました。
ITypeInfo::Invoke
の方が、どうもうまくいきません。
引数の指定の仕方がよくわかりません。
ITypeInfo::CreateInstance
の方は、
pTypeInfo->lpVtbl->CreateInstance(pTypeInfo, NULL, &IID_IDispatch, &pDispatch);
とすれば、うまくいくことを確認しました。
pTypeInfo->lpVtbl->CreateInstance(pTypeInfo, NULL, &IID_IUnknown, &pUnknown);
としても、うまくいきます。 ですが、IDispatchインターフェースを取るんじゃ面白くないし、 IUnknownインターフェースじゃ、そこから先をどうすればいいのやらわかりません。
この2つを使えば、Dispatchインターフェースを持たないサーバー相手でも、 色々できるんじゃないかと思ったんですけど...。
ExcelのSheetChangeイベントを調べるため次のスクリプトを実行します。
require 'win32ole' type = WIN32OLE_TYPE.new('Microsoft Excel 9.0 Object Library', 'WorkbookEvents') method = WIN32OLE_METHOD.new(type, 'SheetChange') method.params.each_with_index do |arg, i| puts "arg#{i} = " + arg.ole_type + " " + arg.name end
結果は次の通りです。
arg0 = DISPATCH Sh arg1 = Range Target
SheetChangeイベントの第1引数はイベントが発生したWorksheetで、第二引数はRangeオブジェクトであることがわかります。 これは、Excelのヘルプの内容とも一致しています。 では、実際にSheetChangeイベントを使った次のようなスクリプトを実行してみましょう。
require 'win32ole' def event_handler(*args) args.each_with_index do |arg, i| if arg.kind_of?(WIN32OLE) puts "arg#{i} = " + arg.ole_obj_help.name else puts "arg#{i} = " + arg.type.to_s end end end excel = WIN32OLE.new('Excel.Application') excel.visible = true book = excel.workbooks.add event = WIN32OLE_EVENT.new(book, 'WorkbookEvents') event.on_event('SheetChange') {|*args| event_handler(*args) } book.Worksheets(1).cells(1, 1).value = "TEST"
実行結果は、次のようになってしまいます。
arg0 = Range arg1 = _Worksheet
どういう訳か、引数の順序が逆転してしまいます。 event_handlerを呼び出すときに引数の順序を逆にしてしまう バグがWin32OLEに残っていたかと思いました。
ですが、Internet Explorerを使った次のスクリプトを実行すると、
require 'win32ole' puts "------ from TYPELIB ------" type = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents') method = WIN32OLE_METHOD.new(type, 'BeforeNavigate') method.params.each_with_index do |arg, i| puts "arg#{i} = " + arg.ole_type + " " + arg.name end puts "------ from EVENT ------" def event_handler(*args) args.each_with_index do |arg, i| if arg.kind_of?(WIN32OLE) puts "arg#{i} = " + arg.ole_obj_help.name else puts "arg#{i} = " + arg.type.to_s end end end ie = WIN32OLE.new('InternetExplorer.Application') ie.visible = true event = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents') event.on_event('BeforeNavigate') {|*args| event_handler(*args) } ie.Navigate('http://www.ruby-lang.org/')
結果は次のようになります。
------ from TYPELIB ------ arg0 = BSTR URL arg1 = I4 Flags arg2 = BSTR TargetFrameName arg3 = VARIANT PostData arg4 = BSTR Headers arg5 = BOOL Cancel ------ from EVENT ------ arg0 = String arg1 = Fixnum arg2 = String arg3 = NilClass arg4 = String arg5 = FalseClass
この場合は、Type Libraryの情報と実際のBeforeNavigateの引数の順序が一致しています。
ちなみに、Excel 2000 と Internet Explorer 5.5 を使ったときの結果です。 一体、どうするのがいいんでしょうか?
今まで、誰にもこの点を指摘されたことはありませんでした。 Win32OLEを使って、ExcelのSheetChangeを使ったスクリプトを 書いたことがある人はほとんどいないものと思われます。 もっとも、SheetChangeを使ったExcel VBAを書く人も少ないでしょうけど。
上で出てくるRangeは、EXCEL VBA でおなじみのRangeのことです。 RubyのRangeクラスのことではありません。念のため。
さらにバグフィックスなどをしました。 今度こそ1.7にコミットできるでしょうか。
EVENTを利用したいとき、情報を得る手段が無いと思ったので、 WIN32OLE_METHOD#event_interface を追加しました。
それから、私の環境(Windows 2000)ではBCC32でもちゃんと動くようになりました。
いつの間にか sampleの ie.rb が無茶苦茶なことになってました。修正。 さらにバグフィクスとリファクタリング。 ついでに、on_eventのテスト testOLEEVENT.rbを追加。 テストメソッドは1つですけど、無いよりはましです。
『ブラック・エンジェル』松尾由美
『バルーン・タウンの殺人』の作者なので無条件で買い。
EVENTSINK_Constructor
の
pEv = (PIEVENTSINKOBJ)malloc(sizeof(IEVENTSINKOBJ));
を
pEv = ALLOC_N(IEVENTSINKOBJ, 1);
にして、pEv の各メンバーを初期化したら動くようになりました。 これで、コミットします。
しかし、こんな基本的な原因を見つけるのに1週間近くかかるのは駄目すぎです。
hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, &bstr, 1, &count);
のあとの
pev = ole_wc2mb(bstr);
が2度目以降失敗しているような感じ。ole_wc2mb
を使わないで、直接
fprintf(stderr, "pre\n"); pev = ALLOC_N(char, size); fprintf(stderr, "post\n");
とやると二度目以降、post
が出力されずにpre
が出力され続けるというような状況です。
メモリアロケーションかGC絡みとか、なんかその辺りに問題がありそうな気がしてます。
ienavi.rbがうまく動かない件。
よくわかりません。最初のIEからのInvoke呼び出しだけうまく拾えるけど、それ以降は全滅。
どうも 二度目以降の EVENTSINK_Invoke
の処理の中の
hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid, &bstr, 1, &count);
から先へ進まないような感じです。 ひょっとして、次々とやってくるIEからのInvoke呼び出しに追いつけない状態になっている?
再度試してみたら
-LC:\borland\bcc55\lib -LC:\borland\bcc55\lib\psdk
でもうまくできました。 ひょっとしてCRLFじゃなくてLFだったから駄目だったのかもと思い、 (ilink.cfg, bcc32.cfg ともにCygwinのvimで編集してました。)
d2u *.cfg
してから、試してみましたがやっぱりうまくいきました。 ...なんか私は疲れているみたいです。
そういえば、dependからwin32ole.cを外したことを思い出しました。 なんか、Ruby標準の拡張ライブラリだと*.cをdependに追記しているのが主流みたいでしたし、 BCC32だと depend に win32ole.c を含めないと駄目だとなんか勘違いしたみたいです。 ...重症です。
Cygwin、Mingw32、VC++、BCC32 それぞれの Ruby 1.6 と Ruby 1.7 を 1台のPCでコンパイルしていると、混乱して訳がわからなくなってきます。
わたなべさんの情報により
-LC:\borland\bcc55\lib\psdk
を追加してみました。いつもありがとうございます。助けてもらってばかり。
最初
-LC:\borland\bcc55\lib -LC:\borland\bcc55\lib\psdk
と書いてしまったためエラーになってしまいました。 順番が違うのでもなくて、正解は、
-LC:\borland\bcc55\lib -LC:\borland\bcc55\lib\psdk
あっ。dependファイルに、win32ole.cを記述していないことを発見。
うーむ。 コンパイルできるし、have_libraryのチェックは期待通りに動くようになったけど、 ienavi.rbはやっぱりまともに動かないなあ。
うん?
-LC:\borland\bcc55\lib\psdk -LC:\borland\bcc55\lib
の方が正解か?
allocation framework を使っているから駄目なのかと思い、 使わないバージョンのWin32OLEで試してみましたが、症状は変わりませんでした。
どうも、ienavi.rb の
while ($LOOP) WIN32OLE_EVENT.message_loop end
がずーっと動き続けているようです。
ちなみに、Borland C++ 対応版は、 Ruby bcc32の bcc32_ruby172patch020512.zip を利用しています。
1.6版のBCCパッチも試してみるべきか。
遅ればせながら、インストールしました。 Rubyをコンパイルして、make test まで通ることを確認しました。素晴しい。
Win32OLEのコンパイルにも挑戦してみました。
have_library("ole32")
のチェックに失敗します。 チェック飛ばして、強引にMakefileを作ってしまえば、コンパイルできました。 うーむ。ienavi.rbが落ちてしまいます。
ienavi.rb が落ちるのは、fev_s_allocate
でallocateしたオブジェクトを返してなかったからみたい。
VALUE fev_s_allocate(klass) VALUE klass; { obj = Data_Make_Struct(klass,struct oleeventdata,0,ole_event_free,poleev); ... return obj; //コレを忘れてました。 }
でもCygwinもVC++もMingwも無くても平気だったのはなぜ???
落ちなくなりましたが、Internet Explorer 終了しても、スクリプトが終了しません。
Ruby 1.7 で導入された allocation framework を使うようにしました。
ソースを調べて、移動量を指定できることがわかりました。
Control Mod1 l :NudgeRight 5 Control Mod1 h :NudgeLeft 5 Control Mod1 j :NudgeDown 5 Control Mod1 k :NudgeUp 5
などと後に数字を指定すればOKです。省略した場合は2に設定されます。また、
Control Mod1 l :BigNudgeRight
は
Control Mod1 l :NudgeRight 10
と同じです(ヴァージョンは、0.1.8)。
コンソールだと両方のキーがESCになってました。 Xを立ち上げると半角/全角キーがKanjiになってしまいます。
調べてみたら /etc/X11/xinit/Xmodmap.jp というファイルがあって
keycode 49 = Kanji
という行が見つかりました。
直接Xmodmap.jpからこの行を削除してしまおうかと思ったのですが、それはやめて、~/.Xmodmap で
keycode 49 = Escape
としておくことにしました。
Blackboxの後継になるらしいウィンドウマネージャです。 うちの環境では、ハングアップするのでずっと悩んでいました。 今日になってようやく原因がわかりました。 どうやらLANGUAGEなどで日本語を設定しているとハングアップするみたいです。
キーボードだけでほとんどすべての操作をできる点が気に入りました。 (今使っているThinkPad i1620を買ったときには、マウスも必要かと思い、USB接続のマウスも買いました。 かれこれ、1年以上経ちますが、(トラックポイントが使いやすいということもあって) 今だにマウスを使ったことがありません。)
IceWM ではウィンドウの移動をキーボードで操作できないのが、ちょっと不満でした。 それで、IceWMをやめて、(自分でプログラムしさえすれば)何でもありのsawfishを使っていたんです。 今回 Fluxboxでほぼ同じことができることがわかりました。しばらくこれを使ってみようと思います。 と言っても大した設定はしてなくて、私の設定は、この程度です。
Mod1 j :NextWindow Mod1 k :PrevWindow Control Mod1 l :NudgeRight Control Mod1 h :NudgeLeft Control Mod1 j :NudgeDown Control Mod1 k :NudgeUp
あとは、1回のキーボード操作で移動量を指定できれば言うことないんですけどね。
2.1.5からのアップグレードインストールをやってみました。 (UNIX USERの付録のCD-ROM Vine 2.5 と Vine Plus を使用。)
USB接続のCD-ROMからインストールしました。 途中、エラーで1回異常終了しましたが、再度インストールをやり直したら 何とか最後まで進んだみたいです。
途中で、スワップ領域を増やせと言われたので、素直に増やしました。
ext3を推奨するとのことでしたので、素直に ext3 にしました。
USB接続のCD-ROMも使えました。(抜き刺しは試してません。)
VMWareも3.0にアップグレードしました。
linmodem(ltmodem?)は再インストールしました。
半角/全角(漢字)キーとEscキーを入れ換えていたのですが、元にもどってしまいました。 (キーボードの選択を間違えたのかも知れません。)
読了。
バッタもんはバッタもんでも超一流のバッタもんでした。
私は、マイクル・Z・リューインぐらいは読んだことがあるのですが、 それほどハードボイルドには馴染みがありません。 ですから、パロディがあったとしても、良くわかりませんでした。 馴染みのある人だったら、結構ニヤリとするシーンがあるのかも知れません。
そんな私でも、謎解きとして十分楽しめました。 ところどころにきっちりと伏線を張ってあります。
早くも気になっているのは、このシリーズ第二段のできです。 シリーズ第1作が一番面白いなんてことになりませんように。
この前、extconf.rb の中でPLATFORMを調べて Makefileを作るかどうか判断するように 修正したのですが、やはり、方向性が間違っていました。
元々Makefileを作るかどうか判断するために利用していたhave_libraryのチェックが 生きてないことに昨日の段階で気づいたんです。
調べてみたら、
require "mkmf" puts have_library("ole32", nil)
というのを実行すると結果は、必ずtrue になることがわかりました。 元々have_libraryを使ったチェックがチェックになってなかった訳です。
have_library("ole32")
とすれば、ちゃんとチェックしてくれるので、PLATFORMを調べるのはやめて
have_library("ole32")
でチェックするように修正しました。
昨日の修正は、ちょっと方向性が間違っているような気がしてきました。 元気になったら考えてみます。(今日は体調が悪いのです。)
ちょっと前にsubscribeしたのですが、今だに一通も届きません。 ruby-talkの流量からして、絶対変です。 そろそろ、statで自分がちゃんとsubscribeされているかどうか確認した方がいいかも知れません。 などとと思い始めていたのですが...。 どうやら、まだ1通も流れていないらしいです(ruby-list:35020)。 もうしばらく様子を見ます。
Vine Linux 2.1.5 で makeしてみました。 extconf.rb が Makefileを作って、makeを実行してしまいました。 当たり前ですがコンパイルエラーでこけてしまいました。 結局、rubyができませんでした。 まずいので、extconf.rbをちょこっと修正しました。
標準添付に向けての作業です。 コンパイルできないと最初からわかっている環境では、 他に悪影響をおよぼすことなくrubyができることを確認しておこうと思ったのでした。
今日から仕事。
他のサイトにリンクしないのは あんまり他の(ミステリ関係の)サイト(のミステリな記述)を読んでないからなんです。
だらだらと過ごした黄金週間も終わり。
2時間以内で読んでしまいました(笑)。
出だしの文章にちょっと戸惑ってしまい、素直に入りこめませんでした。
1人の登場人物が物語の語り手となる小説があります。 そのような小説は、私も読み慣れています。
ですが、この小説では、あたかも一人の登場人物が語るかのように作者が語るのです。 地の文章が、いわゆる客観的な文章でなくて、作者が表に登場してきている文章とでも言えばいいでしょうか。 ちょっとその手法に不慣れだったもので、戸惑ってしまいました。 もっとも、最初の出だしだけで、後はそれほど気にならなくなりましたが。 (最初の出だしの部分で、それが顕著だったのかも知れません。)
「読む2時間サスペンス」なので、いわゆる謎解きミステリを期待するとがっかりするかも知れません。
『私の!名探偵。』
書店で見つけたので購入。
『学寮祭の殺人』 D.L. セイヤーズ
『不正アクセス調査ガイド』
Software Design
CD-ROM につられて。
『囁く谺』 ミネット・ウォルターズ
謎解きだの複雑なプロットだのそんなことはどうでもいいのです。 これはホームレスの少年テリー・ダルトンが主役の小説なのですから。 彼がすべてなのです。 『ストリート・キッズ』のニール・ケアリー(の少年時代)に 匹敵するくらい(それ以上?)の活躍をしてくれます。
『さらば、愛しき鈎爪』 エリック・ガルシア
買いました。解説読みました。やっぱりバッタもんです。 でも読みます。
『クリムゾン・リバー』 ジャン = クリストフ・グランジェ
買いました。読みました。
フランスミステリというとセバスチャン・ジャプリゾのような どこかゆったりとしたテンポのサスペンスを思い浮かべます。 ですが、この作品は違います。 ジェフリー・ディーヴァーを思わせるようなテンポのよさがあります。
一見、シリアルキラーの犯罪に思える。 だが、意味もなく殺人を犯すアメリカのシリアルキラーのような犯罪者はフランスにはいない。 そんな犯罪はフランス人向きじゃない。
主人公の刑事はこう考えます。 実は、これは、作者から読者へのメッセージでもあるように思いました。 刑事を通じて、このミステリはシリアルキラーが登場する単なるサイコ・サスペンスとは 一味も二味も違うんだぞと 作者自ら読者に啖呵を切ってみせているんじゃないでしょうか。
そういう意味でも、ジェフリー・ディーヴァーを思わせるような作品に仕上がっています。
『囁く谺』 ミネット・ウォルターズ
いきなり文庫本での登場です。これまでハードカバーだったのに、なぜいきなり文庫? できが良くないのではと邪推してしまいます。 文庫本の方が安いし、場所もとらないので、嬉しいんですけどね。
XP エクストリームプログラミング検証編
ううっ。今回は分厚いです。
ソフトウェア職人気質
やっと手に入れました。
ソフトウェア再利用の神話
プロローグの最初の数行を立ち読みして、ツボにはまってしまいました。 再利用は、昔話ですらなく神話の時代の話になってしまったということでしょうか。 何とも意味深なタイトルです。
たのしいRuby
他人に薦めておいて、自分が持ってないのもどうかと思いまして。
各部の引用の中で、読んだことがある作家は竹本健治だけでした。 でも「入神」という作品は知りませんでした。 ひょっとして『閉じ箱』の中の1篇にあったのかなあと思ったのですが、違いました。 マンガだったのですね。
全然関係ない話ですが、『閉じ箱』が角川ホラー文庫に入ったとき、 ホラー文庫ってのはいかがなものか?と思ったのは 私だけなんでしょうか?
...いや、まあ、そんなことはどうでもいいんですけど。
『私の!名探偵。』 都築紫亜
実は、この方から直接メールを頂いたことがあります。 Googleなどで「都築紫亜」とかで検索すると 私のページが上位に来ちゃうんですね。 それで、著者の方に見つかってしまったのでした。 一言触れただけなのに...。
そこでちょっと実物を見なくてはと思って探したのですが、見つけられませんでした。
SRの会から届きました。
海外ミステリは、ベスト10のうち1作だけ読んでいました。
悔しかったのは、何度も書店で目についたのに 手を出さなかった本が上位にランクされていたことです。
だって、タイトルが『さらば、愛しき鈎爪』ですよ。 主人公が恐竜なんですよ。 しかも、人間社会で探偵をやるんですよ。 恐竜がハードボイルドやるんですよ。(←日本語の使い方間違ってます。) 表紙は、恐竜が帽子つけてトレンチコートを着てる絵ですよ。 いかにもバッタもん臭いじゃないですか。
国内の方では、1冊も読まなかった癖に17冊も適当に取り上げたうち 3冊がベスト10に入ってました。(今もまだ1冊も読んでいません。) 実は短篇集は別集計になっているのですが、この17冊のうち2冊が短篇集部門の上位にランクされていました。 合計5冊ということです。 1冊も読まずして、合計5冊がランクインしていたというのは我ながら見事という他ないでしょう。 (←意味不明です。)
...そんなことはどうでも良くて、ちょっとショックだったのは、 サラ・コードウェルが亡くなったということです。 知りませんでした。 『セイレーンは死の歌を歌う』『黄泉の国へまっしぐら』などのタイトルが思い出されます。 原作では探偵役のテイマー教授が男性か女性かわからないという凝った書き方をしているそうです。 翻訳でもその点には注意したというのをどこかで読んだことがあります。 結局、男性か女性かわからないままになってしまったんでしょうか。
遅ればせながらcmailでUTF-8のメールでも読めるようにしました。
Mule-UCS をインストールします。
tar zxvf Mule-UCS-0.84.tar.gz cd Mule-UCS-0.84 emacs -q -no-site-file -batch -l mucs-comp.el su cp -r lisp /usr/local/share/emascs/site-lisp/mule-ucs
あとは、.emacs
に
(setq load-path (append '("/usr/local/share/emacs/site-lisp/mule-ucs") load-path)) (require 'un-define)
と書いておくだけです。
Emacs 21.2 だと起動に時間がかかるため、そのためのパッチがあります。 URL忘れました。 patch emacs 21.2 mule-ucs あたりで Google などで検索してみれば それらしきものが見つかると思います。