mrubyエンジンのcp932化の手順

概要

ここではmrubyをScenarioModに組み込む上では避けて通れない、
mrubyのcp932対応や、必要な措置について記載しています。

mrubyとは

mruby は、まつもとゆきひろ氏が中心となって開発しているRubyを、組み込み向けに軽量・小型化した言語です。

RubyとLuaは誕生時期がほぼ同時期でですが、
LuaがC言語アプリケーションの組み込み用途として設計され、数多く採用されているに対し、
Rubyは、Perlの代用やRuby on Rails を切っ掛けとしてWeb方面へと花開きました。
mrubyとは、そのようなrubyの応用範囲を広げるべく、組み込み用途向けに仕立て直したものです。

しかし、この分野のでLuaの優位性はかなり高く、2015年現在、mrubyを採用するプロダクトは未だ数は少ないです。
ですが、元々Rubyの使い手であれば、導入は一考に値するでしょう。

ダウンロード

更新日 2016/01/22
mruby-master-cp932-1.1.0.01.zip

これらダウンロード対象となるソースは、mrubyをcp932(≒sjis)に対応したバージョン一式である。
この章の内容を理解する上で参考にしてください。

cp932に対応させる必要性

天翔記本体は、cp932で構成されており、各種データも全てcp932である。
そして、ScenarioModもcp932であり、ModDebuggerもcp932である。
以上から、mrubyをScenarioModで使う上においては、mruby本体のレベルからcp932にある程度は対応する必要がある。

mrubyコンパイルのための前準備

ここに記載されている情報は、mruby v1.1.0 2014/11/19版でのものとなる
mrubyのバージョンアップに伴い、コンパイルの仕方やファイル構成等が変更になっている可能性が高いことを踏まえた上で記事を読んで欲しい。

  • 最新版のmrubyダウンロード

    Github の mruby から「Download Zip」等でダウンロード。

  • rubyのインストール

    ruby for windows 系が入ってない人は、rubyを入れる。
    コンパイルに必要です。
    rubyinstaller.org
    (パスを通す必要あり)

  • bison for windowsのインストール

    bison for windows 系が入ってない人は、bisonを入れる。
    コンパイルに必要です。
    bison for windows
    (パスを通す必要あり)

mrubyのcp932対応

  • 完全対応する必要はない

    luaもそうですが、cp932に対応といっても、フルに対応する必要はありません。
    いわば、「バイト列」としての扱いのまま、cp932文字コードで「エラー」が出ない状態であれば十分と言えます。

    いわゆるLuaのcp932化と同じレベルものものを目指します。

  • mbenc.hの作成

    まず、mbenc.hというファイルを作ります。

    /*
    ** mbenc.h : MS-Windows用マクロ
    **
    ** mruby の cp932 encoding用
    ** by 翔.jp
    */
    
    #ifndef mbenc_h
    #define mbenc_h
    
    
    #define MRUBY_USE_ENC_CP932   1
    
    
    /* -- japanese cp932 -- */
    #if MRUBY_USE_ENC_CP932
    #define is_lead_byte(c) ((0x81 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0x9f) || (0xe0 <= ((unsigned char) (c)) && ((unsigned char) (c)) <=0xfc))
    #else
    #define is_lead_byte(c) (0)
    #endif
    
    
    #endif
    
       

    このファイルをmrubyの「\mruby-master\include」ディレクトリの中に入れましょう。

  • parse.yの編集

    次に、parse.yというファイルが、mruby-master\src\parse.y という場所にあります。

        static int
        parse_string(parser_state *p)
        
    の関数のwhile文内の一番下あたりが、
            pushback(p, c);
            return tLITERAL_DELIM;
          }
          else {
            pushback(p, c);
            tokfix(p);
            yylval.nd = new_str(p, tok(p), toklen(p));
            return tSTRING_MID;
          }
        }
        tokadd(p, c);
      }
    
      tokfix(p);
      p->lstate = EXPR_END;
      end_strterm(p);
    
      if (type & STR_FUNC_XQUOTE) {
    

    のようになっていますので、
    (※バージョンが違うと少々違うかもしれませんが、とりあえず似た場所があるはずです)

            pushback(p, c);
            return tLITERAL_DELIM;
          }
          else {
            pushback(p, c);
            tokfix(p);
            yylval.nd = new_str(p, tok(p), toklen(p));
            return tSTRING_MID;
          }
        }
        {
          int is_cp932 = 0;  /* cp932用 */
          if ( is_lead_byte( c ) ) { /* cp932の範囲だったらフラグ立て */
            is_cp932 = 1;
          }
    
          tokadd(p, c); // 文字コードに関わりない処理。
    
          if ( is_cp932 && c != EOF ) { /* cp932の範囲だったらもうひとつ無条件で処理してしまう */
            c = nextc(p);
            tokadd(p, c);
            is_cp932 = 0;
          }
        }
      }
    
      tokfix(p);
      p->lstate = EXPR_END;
      end_strterm(p);
    
      if (type & STR_FUNC_XQUOTE) {
    

    と書き換えます。

    同じファイルの先頭のヘッダー部分に

    #include "mruby.h"
    #include "mruby/compile.h"
    #include "mruby/proc.h"
    #include "mruby/error.h"
    #include "node.h"
    #include "mrb_throw.h"
    #include "mbenc.h" // for cp932
    

    を足しておきましょう。

  • VC++ 2013のコンパイルオプション

    さて、Windowsでは通常、VisualStudioでプログラミングするでしょう。
    その場合、mrubyはVC++ Desktop 2013以上でコンパイルすることとなります。

    さて、それを踏まえて
    mruby-master\tasks\toolchains\visualcpp.rake
    を開けて、以下の強調してる行のオプションを変更します。

    
    MRuby::Toolchain.new(:visualcpp) do |conf|
      [conf.cc].each do |cc|
        cc.command = ENV['CC'] || 'cl.exe'
        # C4013: implicit function declaration
        cc.flags = [ENV['CFLAGS'] || %w(/c /nologo /W3 /we4013 /Zi /MT /Ox /Oi /Ot /D_CRT_SECURE_NO_WARNINGS)]
        cc.defines = %w(DISABLE_GEMS MRB_STACK_EXTEND_DOUBLING)
        cc.option_include_path = '/I%s'
        cc.option_define = '/D%s'
        cc.compile_options = "%{flags} /Fo%{outfile} %{infile}"
      end
    
      [conf.cxx].each do |cxx|
        cxx.command = ENV['CXX'] || 'cl.exe'
        cxx.flags = [ENV['CXXFLAGS'] || ENV['CFLAGS'] || %w(/c /nologo /W3 /Zi /MT /Ox /Oi /Ot /EHsc /D_CRT_SECURE_NO_WARNINGS)]
    

    VC++ Desktop2013の「VS2013 x86 Native Tools コマンド プロンプトを開く」を使います。
    VC++ Desktop2013 ではショートカットが存在しない場合がありますので、無い場合は自分で制作しましょう。
    デスクトップにショートカットを作成して、

    %comspec% /k ""C:\Program Files (x86)\Microsoft Visual Studio 13.0\VC\vcvarsall.bat"" x86
    

    みたいなのを作成します。
    実際には、VC++2013をインストールしたディレクトリにあわせて書き換えてください。

  • 先述のVC専用コンソールに話を戻して、コンソールを立ち上げて、
    そこまで、ディレクトリを移動してから、

    PICTURE

    ruby ./minirake
    

コンパイル出来ない場合

コンパイルできない場合、大抵「Cの関数」が、「VC++に無い」というだけです。

ほとんどの場合は、エラーが出る該当の関数をWEBで検索すれば対処方法がわかります。
大抵は、「関数名の先頭にアンダーバー」を付けて、「何らかのヘッダーを追加すれば」
同様の関数が存在するのでコンパイルが通ります。

その他

cp932化した状態でコンパイルさえできてしまえば、後は通常のmrubyと変わるものではありません。
普通にScenarioModやShiftJis系アプリに組み込めますので、
mrubyの使い方などをWebで調べていけば、問題なく使えるはずです。