ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja ja en ja ja ja en fa kn ja ja ja en en en en en de ja en ja en ja ja ja ja en ja ja ja de uk ru uk uk ta en en fa de kn en fa ceb fa en kn en de ceb en pt kn en cs en ceb uk kn en en de ja de ja ja ja
mswin32-ruby16.lib をプロジェクトに追加する必要が有ります。mingw版バイナリでは lib ディレクトリに入ってますが、これは(多分)VC用なので、このままでは使えません。コマンドプロンプトで
coff2omf mswin32-ruby16.lib mswin32-ruby16-bcb.lib
としてBCC版Libファイルを作り、これをプロジェクトに追加しましょう。ついでに、Rubyの bin ディレクトリの mswin32-ruby16.dll をSystemディレクトリにコピーしておきましょう。
○必要な関数を定義する
Ruby/KAKASI拡張モジュールなどを見れば分かるように、 Init_dlltest (dlltest の所はプロジェクト名)などの関数を定義します。C++で書いてる場合は、
extern "C"{
void Init_dlltest();
のように、関数宣言を extern "C"{ … } で囲みます。関数定義を囲む必要は無いです。この辺の関数の書き方について詳しくは README.EXT.ja を読んでください。
○関数をエクスポートする
普通なら、関数に __export や __declspec(dllexport) を付ければエクスポート完了!なんですが、これだと例えば _Init_dlltest のように、エクスポートされた関数名の先頭にアンダスコアが付いちゃうんですね。で、これだとRubyがうまく呼び出せないようです。そこで「モジュール定義ファイル」ってのを作ります。
CODEPRELOAD MOVEABLE DISCARDABLE
DATAPRELOAD MOVEABLE SINGLE
HEAPSIZE4096
STACKSIZE1048576
Init_dlltest=_Init_dlltest
こんな風に書いたものを、 dlltest.def として dlltest.bpr と同じディレクトリに保存します。最後の行が、「内部名 _Init_dlltest の関数を Init_dlltest という名前でエクスポート」と言う意味な訳ですね。で、[プロジェクト]-[オプションソースの編集]で
に書き換えます。これでメイクすれば、 Init_dlltest という関数がエクスポートされた dlltest.dll ができます。 eXeScope などのツールで確認できます。ちなみに、 rb_define_module_function などで登録した関数をエクスポートする必要は無いようです。
ここで1つ注意点。BCB6のバグなのか、オプションソースのDEFFILEの設定は、プロジェクトを開きなおすとクリアされてしまいます。メイクする前に一旦 dlltest.bpr.xml のタブを閉じて開きなおし、DEFFILEの設定がクリアされていれば書き直しましょう。*1
require 'dlltest'
とすれば、以後、 dlltest.dll で定義したモジュールやクラスが使えます。 dlltest.dll はRubyファイルと同じディレクトリか、Systemディレクトリ辺りに置きましょう。
Rubyの require '***' とDLLの Init_*** 関数で、***の部分(ここでは"dlltest")の大・小文字が違うと失敗します。小文字で揃えるのが無難そうです。
--- dlltest_main.cpp ---
#pragma hdrstop
using namespace std;
extern "C"{
void Init_dlltest();
VALUE rb_DllTest_hello(VALUE obj);
void Init_dlltest()
VALUE module= rb_define_module("DllTest");
rb_define_module_function(module, "hello", (VALUE (*)(...))rb_DllTest_hello, 0);
VALUE rb_DllTest_hello(VALUE obj)
cout << "Hello world." << endl;
return INT2NUM(0);
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
--- test.rb ---
require 'dlltest'
DllTest.hello()
*1 毎回DEFFILEを書き直すのがうざい方は、[プロジェクト]-[メイクファイルの作成]でメイクファイル(例:dlltest.mak)を作成しましょう。コマンドプロンプトで
make -fdlltest.mak
とすると、統合環境を使わずにDLLをメイクできます。ただしこの場合、ファイルの追加などのためには手動でメイクファイルをいじる必要が有ります。