2002年2月の雑感

更新日:2002-02-25
[トップページへ] [1月] [3月] [過去の雑感へ]

2月25日(月)

疲れ

なんかこのままの状態で明日を向かえると、結構まずいので、 体力回復のため早く寝ます。 Win32OLEの標準添付化作業はちょっとお休み。


2月24日()

Mozilla 0.9.8 (Vine Linux 2.1.5)

Linux Japanが届きました。 早速 CD-ROM から Mozilla 0.9.8 をインストールしました。 今月で定期講読の期間が終わります。 継続手続きはしないかも知れません。


2月23日()

のんびり

ちょっと疲れている感じなので、のんびり過ごす。

ActTitle 0.9.0 (Vine Linux 2.1.5)

IceWMではタスクバーに時刻を表示できたのだがgolemにはその機能がありません。 ちょっとつらいので ActTitleをインストールしました。

./configure
make
make install

設定ファイル ~/.acttrc を acttrc.ja を元に作ります。

date @ now {
        format = "%Y-%m-%d(%a) %H:%M";
}

で acttitle を起動します。あれっ? 何も表示してくれませんよ。 それどころか、元々表示されてたタイトルの文字まで消してくれてます。

いろいろフォーマットを変更して試して、ようやくタイトルに日本語を表示できないことに気づきました。 別に日本語を表示できなくても構わないので、

LC_LANG=C LC_LANGUAGE=C LC_ALL=C acttitle

と実行することにしました。 デフォルトでは更新間隔が1分なので実際の時刻とちょっとずれてしまいます。 1秒間隔にするほどのこともないので、とりあえず、更新間隔を10秒間隔にしておくことにしました。

date @ now {
        interval=10s;
        format = "%Y-%m-%d(%a) %H:%M";
}

2月21日(木)

Win32OLE(Ruby)

標準添付へ向けて残りの作業

1.7対応に関しては、ちょっと調べた範囲だとさほどインパクトが無さそう。 ドキュメントはちょっと時間がかかるかな。

また、ここまで、とりあえず動くように実装するのを優先して、作業を進めてきたので、 リファクタリングの時間をちょっとだけ取ることにした。

sampleとtestsはそのまま入れておくことにした。 だけど、どんな環境でも動くようなものにはなってない。 Excelをはじめ、いろんなものが入ってないと駄目。 そもそも、自分では何もしない、何もできない、 他力本願コバンザメ拡張ライブラリだからしょうがない。

testsの方は、test専用OLEサーバーを作れば、自己完結するけど そこまでするだけの気力が無い。

Win32OLE(Ruby)

artonさんの意見も取り入れて、 WIN32OLE_EVENT.on_event_with_out_args というのを追加。 WIN32OLE_EVENT.on_event_with_array_argv は削除しました。 次のようにします。

require 'win32ole'

def new_window2(ppdisp, cancel, args)
  puts "new_window2 Event"
  # prevent the new window
  args[1] = true
end

ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents2')

ev.on_event_with_out_args("NewWindow2") {|ppdisp, cancel, args| 
  new_window2(ppdisp, cancel, args)
}

第3引数は、Internet Explorerに返すための配列の引数です。 argsは空の配列なので、引数を参照したい場合は、ppdisp, cancelの方を参照してください。

標準添付に向けて残っている作業は

こんなとこでしょうか。

golem (Vine Linux 2.1.5)

私は、他人に影響されやすいです。 今回も影響されて、Icewm をやめて golem を使い始めました。 なかなか軽くていいです。

以前、blackboxを試したことがありました。 そのときは、フォーカスの切り替えなどの操作に違和感を覚え、すぐにIcewmに戻りました。 今回はそのような違和感も無いので、このまましばらく使い続けるかも知れません。

なんかインストールはうまくいかなくて、一部のファイルを手動でコピーする必要がありました。

golem.installを実行すると、~/.xinitrc と ~/.xsession を作ります。その中で、

exec golem

として、golemを起動するようになってます。

この方法は、Vineとはちょっと違うので、Vineに合わせて(?) ~/.Xclientsを使うことにしました。

cp /etc/X11/xinit/Xclients ~/.Xclients

としてから .Xclients の中に

golem*)
    startWM golem golem
    ;;

というのを追加しました。 後は、~/.wm_style を

golem

に変更しておけばOKです。

と言いながら、sawfishもちょっと気になってインストールしました。


2月19日(火)

こんな私はcmail

Emacs 21にしたので、気づいたのだけど、 emacs-w3mにはタブブラウザ機能があったり、 Forwardボタンなどがあったりして、 w3mとは別物のように思えてしまう。

別物だと割り切ってしまえば、 w3mとのキーバインドの違いも気にならないのだが、 なまじ名前にw3mとついているのでどうもひっかかる。 いっそのこと全然違う名前にしちゃったらどうだろうかと思ったのだが それでは、w3mに対して失礼ではないかとも考え、w3mの雰囲気を残しつつ w3mとは全然違う名前ということで、

w3m

を180度ひっくり返して

mEw

なんて名前はどうだろうかとふと思ったんだけど、それだと キーバインドの違いじゃなくて、 「なんでメールが送信できないんだよお。」と機能の違いが気になる人が 出てくるんじゃないかと心配になり、 ひっくり返す方がよほど、w3mに対して失礼なんじゃないかとも思えてきて この名前も良くないなあという結論になってしまった。

名前は難しい。


2月16日()

RDoc (Ruby)

なんだ。RDocでも同じようなことが できるようになってたのか([ruby-talk:33673])。

引導

Win32OLEに対するnew_window2メソッドの中で、 呼出元(EVENTSINK_Invoke)の値にまで影響を与えるという最近の取り組み。 [ruby-list:33931]でまつもとさんから引導を 渡されちゃったような気がするのは気のせいだな。きっと。うん。そうに違いない。 いや。まあ。Rubyレベルでできないことは最初から百も承知なんですけど。

Emacs 21

インストールしてみた。 めでたく、screen内で emacs -nw -f cmail でも色がつくようになった。

Win32OLE (Ruby)

結局、WIN32OLE_EVENT.on_event_with_array_argv というのを導入してみました。

require 'win32ole'

def new_window2(args)
  puts "new_window2 Event"
  # prevent the new window
  args[1] = true
end

ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents2')

ev.on_event_with_array_argv("NewWindow2") {|args| 
  new_window2(args)
}

引数を配列で渡すという方法です。 new_window2の引数は必ず配列にする必要があります。 かなり苦しいです。

artonさんの案がどういうものかまだよくわかっていません。 artonさんの案の方がよいとわかればそっちに変更します。


2月15日(金)

Win32OLE (Ruby)

なかなか、すんなりといい案が出てきません。 結局、OLEとRubyの仕組みというか、設計思想というか、デザインというか、なんかわからんけど、 何かが根本的にどこかで違っているから、 すんなりいかないのではないだろうか と思ったり、思わなかったりしないでもない今日この頃です。

RUDE4C

Rubyの拡張ライブラリからクラスやモジュールやメソッド定義を抜き出すツール RUDE4C。 あとで、Win32OLEに試してみよう。


2月14日(木)

Win32OLE (Ruby) & ruby-list

[ruby-list:33853]が最近の私のWin32OLEに対する取り組みと重なって 興味深く感じてしまいました。 決して、ここから続くスレッドの中で、RubyUnitが取り上げられたり、 極道編が取り上げられたりしているからではありません。

私が取り組んでいるのは、ここで触れていることとは逆のことだからです。 つまり、def文の中の実行文で外部の変数に影響を与えたいのですね。

def new_window2(ppdisp, cancel)
  cancel = true
end

EVENTSINK_Invokeの中から上のnew_window2を呼び出したときに、 new_window2の中の実行文による、cancelの変更を 外部(呼び出し元)のEVENTSINK_Invokeにまで影響させたい訳ですから。

で、この後に続く[ruby-list:33856]で配列やハッシュを戻り値にして 呼び出し元に伝える話が出てきます。 実は、この手法も1つの解決案として考えたことがあります。

def new_window2(ppdisp, cancel)
  cancel = true
  [ppdisp, cancel]
end

という風にしてから、EVENTSINK_Invoke側でnew_window2の戻り値をそのまま、 InternetExplorer側に返してやるというものです。

残念ながらこれもボツになりました。 採用に至らなかった理由は、結局 new_window2を定義する側が、必ず戻り値を意識しなければならなくなるのが面倒だからです。

例えば、

$args = []
def new_window2(ppdisp, cancel)
  $args.push ppdisp
  $args.push cancel
end

とした場合でも、戻り値は、

[ppdisp, cancel]

になってしまいます。 これをそのままInternet Explorerに返してしまっては、new_window2を 定義した側が驚き、予想外の結果を引き起こす可能性もあります。 そういう訳でボツになってしまったのでした。

しつこく続く...。


2月13日(水)

Win32OLE (Ruby)

安直な解決編は、やはり安直でしかなく、欠陥が見つかりました。

ボツにした案その2です。

その案は、WIN32OLE_EVENT::ARGV という定数を導入するというものです。

まず、Init_win32oleの中で WIN32OLE_EVENT::VARIANT を定義します。

rb_define_const(cWIN32OLE_EVENT, "ARGV", rb_ary_new());

でもって、EVENTSINK_Invokeの中で、new_window2を呼び出す直前にARGVを空にします。 new_window2を呼び出した後で、pdispparamsの中身をARGVの中身で書き換えてやります。

/* ARGVの中身をクリア */
argv = rb_cvar_get(cWIN32OLE_EVENT, rb_intern("ARGV"));
rb_funcall(argv, rb_intern("clear"), 0);

/* new_window2 を呼び出す。*/
rb_apply(handler, rb_intern("call"), args);

/* ARGVでpdispparams構造体の中身を書き換える */
ary2ptr_dispparams(argv, pdispparams);

new_window2側では、WIN32OLE_EVENT::ARGVに上書きしたい内容をセットするというものです。

def new_window2(ppdisp, cancel)
  WIN32OLE_EVENT::ARGV[1] = true
end

WIN32OLE_EVENT::ARGV[0] が NewWindow2イベントの第1引数ppdispに、 WIN32OLE_EVENT::ARGV[1] が NewWindow2イベントの第2引数 cancelに対応します。

cancel = true

と上書きする代わりに

WIN32OLE_EVENT::ARGV[1] = true

としてもらおうということです。

スクリプトを書く方にすれば、ちょっとわかりにくいシンタックスになってしまいます。 この方法は、いい方法とは言えません。

でも、欠陥というのは、そのことではありません。

EVENTSINK_InvokeはInternet Explorerから呼び出されます。 どんなタイミングで呼び出されるかわかりません。 その中で、WIN32OLE_EVENT::ARGV というグローバルな定数を利用しているのが欠陥です。

  1. Internet Explorer が EVENTSINK_Invoke を呼び出す。

  2. WIN32OLE_EVENT::ARGV クリア

  3. EVENTSINK_Invokeが new_window2 を呼び出す。

  4. new_window2の実行が終了する前に EVENTSINK_Invokeが呼び出される。

  5. WIN32OLE_EVENT::ARGV クリア

  6. EVENTSINK_Invoke が new_window2 または他のコールバックルーチン(ブロック)を呼び出す。

  7. 最初の new_window2の処理が終了。

  8. WIN32OLE_EVENT::ARGV を pdispparams にセット...したいけど、 WIN32OLE_EVENT::ARGVの値はどうなってるの???

ということでなんかまずそうな気がしたのでボツになりました。

以下続く...。


2月12日(火)

Win32OLE (Ruby)

ちょっと間が空きましたが、続きです。

  1. new_window2で第2引数がtrueになったことをEVENTSINK_Invokeが認識する。 (または、new_window2から、EVENTSINK_Invokeに第2引数がtrueになったことを伝える。)

  2. EVENTSINK_InvokeがInternet ExplorerにNewWindow2の第2引数がtrueになったことを伝える。

これらの問題を解決する方法ですがボツになった案を紹介します。

ボツにしたのはWIN32OLE_VARIANT クラスを導入する方法です。

次のような構造体を定義します。

struct variant {
    VARIANT *pvar;
}

次に、Init_win32ole の中で、WIN32OLE_VARIANT クラスを定義しておきます。 また、WIN32OLE_VARIANT#=メソッドを定義しておきます

cWIN32OLE_VARIANT = rb_define_class("WIN32OLE_VARIANT", rb_cObject);
rb_define_method(cWIN32OLE_VARIANT, "=", folevariant_setval, 1);

new_window2への引数を生成している次の部分

args = rb_ary_new();
...(中略)
// make argument of event handler
for (i = 0; i < pdispparams->cArgs; ++i) {
    VARIANT *pVariant = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
    rb_ary_push(args, ole_variant2val(pVariant));
}

を、次のように書き変えます。

args = rb_ary_new();
...(中略)
// make argument of event handler
for (i = 0; i < pdispparams->cArgs; ++i) {
    v = Data_Make_Struct(cWIN32OLE_VARIANT, struct variant,0,variant_free, pvariant);
    pvariant->pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
    rb_ary_push(args, v);
}

こうしておけば、new_window2の引数はWIN32OLE_VARIANT型になります。

def new_window2(ppdisp, cancel)
  cancel = true
end

としたときに cancel は WIN32OLE_VARIANT型なので、cancel = trueWIN32OLE_VARIANT#=メソッド、つまり folevariant_setval関数が呼ばれます。 あとは、この関数の中で、pvariant->pvarの値を変更すればいいのです。

一見良さそうに思えたのですが、次のようなことをされると困りそうです。

$cancel
def new_window2(ppdisp, cancel)
  $cancel = cancel
end
 ....
$cancel = false 

$cancelの実体である variant 構造体の pvar メンバは

pvariant->pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];

なので、EVENTSINK_Invoke 関数の中だけで有効なのです。

$cancelの値は new_window2の外部でどうするか決められなかったので、この案はボツにしました。

イベントに対するコールバックの引数は、そのコールバックの中だけで有効

というルールにすることも考えました。 ですが、ルールはルールでしかありません。 上のような困ってしまうコードを防ぐことができません。 残念ながらボツにしてしまいました。

えーと...。 ボツにした理由を書いておかないと、忘れそうなので、ここに書いておくことにしました。

以下、安直な解決篇へ続く...。 (←誰も読んでないんじゃないかという気がするが、それは気のせいだと思うことにしよう。)

cmail

ありがとうございます。 使わせてもらいます。

『探偵ガリレオ』東野圭吾 読了

最後の作品だけちょっと無理矢理、科学とミステリを結びつけたような気がしないでもありません。 『爆ぜる』で本当は最後にするつもりだったんじゃないかと邪推してます。


2月8日(金)

買った本

cmail (Linux Emacs)

ruby-talkは、Subjectに番号がつかなくなってしまった。 このページを書くときに、[ruby-talk:XXXX]などと参照するときにcmailを起動しても番号がわからない。 そこで、X-Mail-Countも表示するように、cmail-always-shown-headers に追加した。

Win32OLE (Ruby)

昨日の続きです。

Internet Explorerからは、NewWindow2イベントがRubyスクリプトに通知され、 次のnew_window2が実行されます。

def new_window2(ppdisp, cancel)
  puts "new_window2 Event"
  # prevent the new window
  cancel = true
end

ここで、

cancel = true

としているにも関わらず、そのことはInternet Explorer側には伝わりません。 Internet Explorerは何事もなかったかのように新しいウィンドウを開いてしまうのです。

ここから先は、Win32OLEのソースコードを調べる必要があります。

ソースコードの中でnew_window2を呼び出しているのは、EVENTSINK_Invoke関数の

rb_apply(handler, rb_intern("call"), args);

です。この後、EVENTSINK_Invoke関数は、何もしないで

return NOERROR;

として終了します。これが問題なのです。

EVENTSINK_Invoke関数は、「NewWindow2イベントが発生したよ」という通知とともに Internet Explorer側から呼び出されます。

NewWindow2には

NewWindow2
A new, hidden, non-navigated WebBrowser window is needed.
 DISPATCH ppDisp in  out 
 BOOL Cancel in  out 

ということからわかる通り、ppDispCancelという2つの引数があります。

これら2つのNewWindow2の引数の情報もInternet ExplorerからEVENTSINK_Invokeに渡されます。 この2つの引数の情報は1つのDISPPARAMS構造体にまとめられ、そのポインタがEVENTSINK_Invokeの 第6引数としてEVENTSINK_Invoke側に渡されるのです。

EVENTSINK_Invoke関数は、この通知を受けて、new_window2メソッドを呼び出します。 このときEVENTSINK_Invoke関数は第6引数DISPPPARAMS *pdispparams(=NewWindow2の2つの引数)の 内容をnew_window2用の引数argsに変換します。この引数の変換処理が次の部分です。

args = rb_ary_new();
...(中略)
// make argument of event handler
for (i = 0; i < pdispparams->cArgs; ++i) {
    VARIANT *pVariant = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
    rb_ary_push(args, ole_variant2val(pVariant));
}

new_window2呼び出し用の引数 argsを作ったらEVENTSINK_Invoke

rb_apply(hander, rb_intern("call"), args)

を実行して、new_window2メソッドを呼び出します。 new_window2メソッドは

cancel = true

を実行して、第2引数を変更しています。 このあと、EVENTSINK_Invoke関数は、new_window2で第2引数が変更されたことを無視して

return NOERROR;

とInternet Explorerに返しています。

だから、Internet Explorerは、new_window2で、 NewWindow2の第2引数(=new_window2の第2引数)がtrueになったことを知らず、 新しいウィンドウを開いてしまうのです。

問題は2つです。

  1. new_window2で第2引数がtrueになったことをEVENTSINK_Invokeが無視している。

  2. このため、EVENTSINK_InvokeからInternet Explorerに第2引数がtrueになっていることが伝わらない。

2つの問題を解決するためには、

  1. new_window2で第2引数がtrueになったことをEVENTSINK_Invokeが認識する。 (または、new_window2から、EVENTSINK_Invokeに第2引数がtrueになったことを伝える。)

  2. EVENTSINK_InvokeがInternet ExplorerにNewWindow2の第2引数がtrueになったことを伝える。

とする必要があります。

2は実現できます。 NewWindow2の引数は、DISPPARAMS構造体ヘのポインタとしてEVENTSINK_Invokeへ渡されてきています。 EVENTSINK_Invoke側で、そのポインタの中身を書き変えれば、 Internet Explorerに第2引数がtrueになったことが伝わります。 (ただし、配列など、すべてのケースに真面目に対応しようとするとかなり面倒です。 今回は、簡単に対応できそうなものだけ対応するつもりです。)

残りは1の方です。 (以下続く...)


2月7日(木)

Win32OLE (Ruby)

昨日までのヘルプを表示する話はちょっと横に置いといて、[ruby-talk:32343]の話です。

本題に入る前に断っておきます。 Win32OLE 0.3.5a を使わないとここに書いてあるスクリプトは動作しません。

私は、最初、[ruby-talk:32343]がどういう意味なのかよくわかりませんでした。 ようやく、[ruby-talk:33057]で何がやりたかったのか理解しました。 結論から言うと、現状のWin32OLEで同様のことを実現するのは不可能です。

何が不足しているかを調べる前に、同じものをWin32OLEを使って書くにはどうするかを考えてみます。

まずは、NewWindow2が何者か調べることにします。 [ruby-talk:33105]のメールから、Internet Explorer(internet control)のメソッドらしいということがわかります。そこで、

require 'win32ole'
ie = WIN32OLE.new('InternetExplorer.Application')
ie.visible = true
ie.ole_methods.each do |m|
  puts m.name
end
ie.quit

なんてスクリプトを実行してみます。 ところが、NewWindow2という名前のメソッドは残念ながら見あたりません。

そこで、ExcelのVBE(Visual Basic Editor)で調べてみることにしました。

まず、[ツール]メニューの[参照設定]を選択します。 注意深く参照可能なライブラリファイルを見ていくと

Microsoft Internet Controls

というのが見つかります。

ここから先もVBEを使って調べてもいいのですが、せっかくなのでWin32OLEを使ってみましょう。

require 'win32ole'
classes = WIN32OLE_TYPE.ole_classes('Microsoft Internet Controls')
classes.each do |c|
  puts c.name
  puts c.helpstring
  c.ole_methods.each do |m|
     puts "  " + m.name
  end
end

上のスクリプトを実行すると、見事に NewWindow2 が見つかりました。

ちょっと話がそれてしまいますが、 「タイプライブラリ名をリストアップするメソッドがあると便利」というのは ExcelのVBEを使わなくても、

WIN32OLE_TYPE.typelibs

なんていうメソッドで参照可能なライブラリファイルをリストアップできれば便利だろうと いうことを意図しています。

話を元に戻しましょう。NewWindow2は何ヶ所かで出てくるのですが、

DWebBrowserEvents2
Web Browser Control events interface
  ...(中略)
  NewWindow2

というのが最も気になるところです。 ここを狙い打って調べてみましょう。

require 'win32ole'
classes = WIN32OLE_TYPE.ole_classes('Microsoft Internet Controls')
web = classes.find {|c| c.name == 'DWebBrowserEvents2'}
puts web.name
puts web.helpstring
new_window2 = web.ole_methods.find{|m| m.name == 'NewWindow2'}
puts " " + new_window2.name
puts " " + new_window2.helpstring
new_window2.params.each do |param|
  print "  " + param.ole_type + " " + param.name
  print " in" if param.input?
  print " out" if param.output?
  puts ""
end

ちょっとまだるっこしいスクリプトです。

classes = WIN32OLE_TYPE.ole_classes('Microsoft Internet Controls')
web = classes.find {|c| c.name == 'DWebBrowserEvents2'}

じゃなくて

web = WIN32OLE_TYPE.new('Microsoft Internet Controls', 'DWebBrowserEvents')

と書けた方が便利だろうし、

new_window2 = WIN32OLE_METHOD.new('Microsoft Internet Controls', 'DWebBrowserEvents', 'NewWindow2")

か、

new_window2 = WIN32OLE_METHOD.new(web, 'NewWindow2')

と書けた方がスマートです。(というのが5日に書いたことの意図ですね。) この辺は、今後のWin32OLEのToDoということで。

さて、スクリプトを実行すると出力結果は次のようになります。

DWebBrowserEvents2
Web Browser Control events interface
 NewWindow2
 A new, hidden, non-navigated WebBrowser window is needed.
  DISPATCH ppDisp in  out 
  BOOL Cancel in  out 

見事に、[ruby-talk:33057]のVBのサンプルと一致しています。

Win32OLEを使ってVBのサンプルをRubyに「翻訳」するとこんな感じでしょうか。

require 'win32ole'

def stop_msg_loop
  puts "Now Stop IE..."
  $LOOP = FALSE;
end

def new_window2(ppdisp, cancel)
  puts "new_window2 Event"
  # prevent the new window
  cancel = true
end

ie = WIN32OLE.new('InternetExplorer.Application')
ie.visible = TRUE

ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents2')

ev.on_event("NewWindow2") {|ppdisp, cancel| 
  new_window2(ppdisp, cancel)
}
ev.on_event("OnQuit") {|*args| stop_msg_loop} 

$LOOP = TRUE
while ($LOOP)
  WIN32OLE_EVENT.message_loop
end

スクリプトは動きます。 IEが起動したあと、新しいウィンドウでリンク先を開こうとすると、 イベントが発生して、ちゃんとnew_window2は実行されます。 ですが、残念ながら、期待している通りにはなりません。 新しいウィンドウが開いてしまうのです。 (以下続く...)


2月6日(水)

Win32OLE (Ruby)

HtmlHelpA API の使い方は間違ってませんでした。 間違っていたのは、Ruby API rb_scan_args の使い方です。

fole_s_showhelp(argc, argv, self)
    int argc;
    VALUE *argv;
    VALUE self;
{
    VALUE helpfile;
    VALUE helpcontext;

    rb_scan_args(argc, argv, "1*", &helpfile, &helpcontext);
    if(helpcontext == Qnil)
        helpcontext = INT2FIX(0);
    pfnHtmlHelpA(GetDesktopWindow(), STR2CSTR(helpfile), 0x0f, FIX2INT(helpcontext));
}

ここで、pfnHtmlHelpA は GetProcAddress で取得した "HtmlHelpA" のポインタです。

rb_scan_argsの第3引数に "1*" を指定した場合、argvの1番目が helpfileに、 argvの残りがすべて配列の形でhelpcontextに設定されます。

例えば、argvの内容が

['VBAXL.HLP', 10425]

の場合、

helpfile = 'VBAXL.HLP'
helpcontext = [10425]

となってしまいます。

ここで、第2引数の(1つの要素から成る)配列をFIX2INTでCの整数に変換するととんでもないことになります。 (今回は偶然にも動き続けましたが、core dump することもあるかも知れません。) FIX2INTは何のチェックもしないでいきなりCの整数に変換しようとするからです。

たまたま値がどうなっているんだろうと思って、

fprintf(stderr, "%d\n", FIX2INT(helpcontext));

としたらとんでもない大きい数に変換されてました。なんか変だなあと思って

NUM2INT(helpcontext);

としてやっと配列になっていることに気付きました。 (FIX2INTと違ってNUM2INTは数値に変換できるかどうかを事前にチェックしてくれます。)

本来は、第2引数が配列にならないように

rb_scan_args(argc, argv, "11", &helpfile, &helpcontext);

とすべきでした。 また、今回の場合は、チェックなしでいきなり、FIX2INTやSTR2CSTRを 使ってCの整数や文字列に変換しているのもまずかったです。 チェックが必要でした。


2月5日(火)

著者と訳者

著者と訳者が同じであることは別に疑問でも何でもないですね。 その通りなんでしょう。 IじゃなくてIIだけをLinux Japanで紹介しているというのは相変わらず疑問です。

Win32OLE (Ruby)

タイプライブラリ周辺のメソッドをいくつか追加した方が、より使い勝手が良くなるかと考えています。 タイプライブラリ名をリストアップするメソッドとか、WIN32OLE_TYPE.new や、WIN32OLE_METHOD.new とか。

ITypeLibのGetDocumentationを使うとヘルプファイルとヘルプコンテキストを得ることができます。 これを使ってヘルプファイルを表示するメソッドをWin32OLEに追加しようとしているのですが、 何も表示してくれません。 (←このようなメソッドをWin32OLEに組み込むべきかどうかは意見の別れるところでしょうが、 表示できないことには、意見もへったくれもないので(笑)、とりあえずそれは横に置いときます。)

きっと HtmlHelpA API の使い方を間違えているんでしょう。 先に純粋なCのプログラムを書いて実験してみますか。


2月3日()

Win32OLE

大幅にいじったので、0.3.5a としてリリース。 olegen.rbも動くようにしたつもり。 ぼちぼちドキュメントも整備しよう。

w3m

久々にコンパイルしようとしてconfigureしたら

Inline image support (you need Imlib library) [n]?

と聞いてきた。 標準サポートになったのか。


2月2日()

Win32OLE

いろいろといじってます。 今から予告しておくと、

なんかは互換性がなくなります。


2月1日(金)

Linux Japan

3月号の「新刊採って出し」で 『理論物理学のための幾何学とトポロジーII』 が紹介されています。 なぜなんでしょうか? さらに、『理論物理学のための幾何学とトポロジーI』は見あたらないようです。

アンケート葉書を出して、編集部にこの疑問をぶつけてみようかと考えております。

さらにさらに、「中原幹夫 著/中原幹夫、佐久間一浩 訳」となっております。 一瞬誤植かと思ったのですが、本の表紙の写真の方も「中原幹夫 著/中原幹夫、佐久間一浩 訳」 となっているように見えます。 謎は深まるばかりです。

原書のタイトルと著者がどうなっているのかという疑問もぶつけてみようかと思います。


[トップページへ] [1月] [3月] [過去の雑感へ]