著作一覧 |
Ruby-2.4.0-preview1のテストをしていて引っかかった。
irb(main):002:0> irb(main):002:0> require 'fiddle' => true => true irb(main):003:0> irb(main):003:0> RUBY_VERSION => "2.4.0" => "2.4.0" irb(main):006:0> irb(main):006:0> lib = 'c:/progra~2/java/jdk1.6.0_45/jre/bin/client/jvm.dll' => "c:/progra~2/java/jdk1.6.0_45/jre/bin/client/jvm.dll" => "c:/progra~2/java/jdk1.6.0_45/jre/bin/client/jvm.dll" irb(main):007:0> irb(main):007:0> File.exist? lib => true => true irb(main):008:0> irb(main):008:0> Fiddle.dlopen(lib) Fiddle::DLErrorFiddle::DLError: : No such file or directoryNo such file or directory from C:/Users/arton/lib/ruby/2.4.0/fiddle.rb:47:in `initialize' from C:/Users/arton/lib/ruby/2.4.0/fiddle.rb:47:in `new' from C:/Users/arton/lib/ruby/2.4.0/fiddle.rb:47:in `dlopen' from (irb):8 from C:/Users/arton/bin/irb.cmd:19:in `' from C:/Users/arton/lib/ruby/2.4.0/fiddle.rb:47:in `initialize' from C:/Users/arton/lib/ruby/2.4.0/fiddle.rb:47:in `new' from C:/Users/arton/lib/ruby/2.4.0/fiddle.rb:47:in `dlopen' from (irb):8 from C:/Users/arton/bin/irb.cmd:19:in ` ' irb(main):009:0> irb(main):009:0>
なんか2重にエコーバックされて気持ち悪いがそこはどうでも良いので無視するとして、File.exist?が存在するといっているのに、Fiddle.dlopenは"No such file or directory"(大事なことなので2度言いましたなのはエコーバックが2重になっているからだろうが、バックトレースは2重にならないのが不思議でもある)をレイズする。
それでFiddle.dlopenがおかしいのだろうとみていたら、dlopen自身はWin32APIのLoadLibraryを直接呼び出しているのだった。
ということは、指定したDLLの有無ではなく、そのDLLがダイナミックリンクしているライブラリがPATHに見つからないことが原因(の可能性がある)。この場合は、JDK1.6.0はMSVCR71.dllを利用していて、そんなDLLをシステムが既定状態では持っていないことが理由だ。したがって、ENV['PATH']に、この場合であればC:\progra~2\java\jdk1.6.0_45\jre\bin"を追加すれば良い(PATHには\を使う必要があると思う。少なくともMSDNのLoadLibraryの説明にはディレクトリセパレータは\でなければならないと明記されている(When specifying a path, be sure to use backslashes (\), not forward slashes (/). ))。(もっとも、dlopenにディレクトリセパレータを/にしたパス名を与えても処理はされる。fiddle.cでは考慮していないが(再確認していないので確度80%)本当は呼び出し時にgsub('/', '\\')するのがMSDNによれば正しい)
というわけで、fiddle.cを読むまでにえらく悩んだ。
ジェズイットを見習え |