ちばと申します.

Windows NT 上の Visual C++ 6.0 で mswin 版 Ruby 1.4.2 をコン
パイルするとき, CFLAGS に /MD オプションを追加すると次のシン
ボルが未解決であると言われてエラーになります.

  ___pioinfo
  __set_osfhnd
  __alloc_osfhnd

なぜ /MD オプションをつけてコンパイルするのかというと, そう
しないと拡張ライブラリの中でファイル入出力がうまくいかないこ
とがあるようだからです.

私が作ろうとしているライブラリはその中で LoadLibraryEx() を
使って別のライブラリをロードするようになっています. ここで 
Ruby からロードされるライブラリを A, A からロードされるライ
ブラリを B とします.

B は A の作成時に作られたインポートライブラリをリンクしてい
て A の関数を呼べるようになっています. B が fopen() でオープ
ンしたファイルのファイルポインタを A の関数に渡して中身を読
もうとすると, A の中で呼んでいる fread() が「Bad file
descriptor」というエラーになります. B の中でオープンした直後
にそのファイルポインタを使って読んでみるとちゃんと読めます.

A と B との中で fread() のアドレスを印刷してみたら, 違う値に
なっていました. ということは, それぞれのライブラリがランタイ
ムライブラリの別々のコピーを持っているのだと思われます.

Visual C++ のドキュメントを見ると, ランタイムライブラリのコ
ピーができないようにするには /MD オプションをつけてコンパイ
ルしろと書いてあります. また, 一つのプロセスで異なる種類のラ
ンタイムライブラリを混在させるなとも書いてあります. というこ
とは, Ruby 本体をまず /MD オプションつきでコンパイルしなけれ
ばならないと思ったので, win32/Makefile と 
win32/config.status とを修正して再コンパイルしたら, 最初に書
いたような状況になったわけです.

なぜ /MD オプションをつけると未解決シンボルが出るのかはわか
りませんが, 未解決になっているシンボルは win32.c の中でソケッ
ト対応の fdopen() を実現するのに使われているようです.

この win32.c というソースファイルは, Perl のソースに含まれて
いるものとよく似ていますが, そこから持ってきたものなのでしょ
うか? Perl の最新版を見てみましたが, Ruby のとはだいぶ違って
いるので, Ruby に含まれているものは Perl のソースから持って
きたとすれば, 少し古いものであると思われます. もしかしたら最
新版を組み込めばコンパイルできるようになるのかもしれませんが, 
どこをどう変えればよいのか見当がつきません.

というわけで, 次のことをご存知の方がいらっしゃれば, 教えて頂
けると助かります. よろしくお願いします.

・Visual C++ で, ある DLL の関数から別の DLL の関数にオープ
  ンされたファイルポインタを渡して入出力できない真の理由は何
  か? それをできるようにするにはどうすればよいか
・Ruby を /MD オプションつきでコンパイルできるようにするには
  どうすればよいか
・Ruby のソースに含まれている win32.c はどこかから持ってきた
  ものなのか. そうであれば, それはどこからか. それを最新版に
  するにはどうすればよいか

                     ちば けいすけ <chiba / lab.imagica.co.jp>