BDS2006(C++Builder)からRubyを使う

Borland Developer Studio 2006(C++Builder)からRubyを使ってみます。

箏音の日記 – C++とRubyC#からRubyのコードを実行するテスト を参考にしました。

Rubyをコンパイルする手間を省くために、Ruby-mswin32 から 最新リリース版である ruby-1.8.4-i386-mswin32.zip をダウンロードします。

ダウンロードした ruby-1.8.4-i386-mswin32.zip を展開し、bin\msvcrt-ruby18.dll をC++Builderのプロジェクトを作成するディレクトリにコピーします。

C++Builderを起動し、VCLフォームアプリケーションを作成します。

まず、起動時にDLLを読み込み、終了時に解放します。

Unit1.hに次のコードを追加。

private:
  HINSTANCE hDll;

Unit1.cppに次のコードを追加。

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  hDll = LoadLibrary("msvcrt-ruby18.dll");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  if (hDll) FreeLibrary(hDll);
}

DLLが正しく読み込まれていることを確認します。

次は、Rubyプログラムを実行してみます。

Unit1.hに次のコードを追加。

private:
  __declspec(dllexport) void (*ruby_init)(void);
  __declspec(dllexport) unsigned long (*rb_eval_string)(const char*);
  __declspec(dllexport) int (*ruby_cleanup)(int);

Unit1.cppに次のコードを追加。

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  hDll = LoadLibrary("msvcrt-ruby18.dll");
  if (hDll)
  {
    ruby_init = (void (*)(void))GetProcAddress(hDll,"ruby_init");
    rb_eval_string = (unsigned long (*)(const char*))GetProcAddress(hDll,"rb_eval_string");
    ruby_cleanup = (int (*)(int))GetProcAddress(hDll,"ruby_cleanup");
  }
}

フォームにボタンを追加し、ボタンを押したときのイベントを記述します。

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  if (!hDll)
  {
    Application->MessageBox("msvcrt-ruby18.dll が見つかりませんでした。",
                            "DLL エラー",
                            MB_ICONSTOP | MB_OK);
    return;
  }
  //Rubyインタプリタの初期化
  ruby_init();
  //スクリプトの実行
  rb_eval_string("File.open('a.txt', 'w' ) { |f| f.puts 'success' }");
  //Rubyインタプリタのクリーンアップ
  ruby_cleanup(0);
}

実行してみましょう。
ボタンを押すとsuccessと記述されたa.txtが作成されると成功。

次に、スクリプトをファイルから読み込んで実行します。

Unit1.hに次のコードを追加。

private:
  __declspec(dllexport) void (*ruby_init_loadpath)(void);
  __declspec(dllexport) void (*rb_load)(unsigned long, int);
  __declspec(dllexport) unsigned long (*rb_str_new2)(const char*);

Unit1.cppに次のコードを追加。

__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
  hDll = LoadLibrary("msvcrt-ruby18.dll");
  (中略)
  ruby_init_loadpath = (void (*)(void))GetProcAddress(hDll,"ruby_init_loadpath");
  rb_load = (void (*)(unsigned long, int))GetProcAddress(hDll,"rb_load");
  rb_str_new2 = (unsigned long (*)(const char*))GetProcAddress(hDll,"rb_str_new2");

フォームにもう一つボタンを作成し、ボタンを押したときのイベントを記述します。

//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  if (!hDll)
  {
    Application->MessageBox("msvcrt-ruby18.dll が見つかりませんでした。",
                            "DLL エラー",
                            MB_ICONSTOP | MB_OK);
    return;
  }

  //Rubyインタプリタの初期化
  ruby_init();
  ruby_init_loadpath();
  // スクリプトをファイルから読み込んで実行
  rb_load(rb_str_new2("test.rb"), 0);
  //Rubyインタプリタのクリーンアップ
  ruby_cleanup(0);
}

test.rbファイルはこう書いてみました。

File.open('b.txt', 'w' ) { |f|
  f.puts 'success'
}

実行してみましょう。
ボタンを押すとsuccessと記述されたb.txtが作成されると成功。

続く

コメント

  1. Pingback: Provia Hylogics » [メモ]インタプリタ言語からネイティブ言語への遷移

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください