IronRuby 1.0における日本語コード変換
IronRuby 1.0ではmodule NKFのModule Functionsが定義されておらず、NKFモジュールおよびKconvモジュールの各機能が使えません。
そこでWindows版のnkfを使ってNKFモジュールおよびKconvモジュールの主要な機能が使えるようにする方法を考えてみました。
1.nkf32.dllをパスの通ったフォルダにコピーする
windows版のnkfは「nkf.exe nkf32.dll Windows用の詳細情報 : Vector ソフトを探す!」からダウンロードできます。
nkf32.dllにはNT版と9x版があります。
Windows XP以降のOSの場合にはNTフォルダの下のnkf32.dllを使用します。
実行環境でパスの通ったフォルダ、例えば
C:\Program Files\IronRuby 1.0\bin
等にコピーします。
2.module NKFのModule Functionsの実装
上記nkf32.dllを使用してmodule NKFのModule Functionsを実装します。
例えば以下のソースをironnkf.rbというファイルに保存します。
require 'nkf' $KCODE="SJIS" require 'Win32API' module NKF @@SetNkfOption = Win32API.new 'nkf32', 'SetNkfOption', 'p', 'i' @@NkfConvertSafe = Win32API.new 'nkf32', 'NkfConvertSafe', %(p i p p i), 'v' @@NkfGetKanjiCode = Win32API.new 'nkf32', 'NkfGetKanjiCode', 'v', 'i' def nkf(opt, str) @@SetNkfOption.call opt ret = "\x00" * (str.size * 3 + 10) ret_len = "\x00\x00\x00\x00" @@NkfConvertSafe.call ret, ret.GetByteCount, ret_len, str, str.GetByteCount ret_len = ret_len[0] + ret_len[1] * 0x100 + ret_len[2] * 0x10000 + ret_len[3] * 0x1000000 ret[0..ret_len-1] end module_function :nkf def guess2(str) nkf "-g", str nkf_ret = @@NkfGetKanjiCode.call k_code = NKF::UNKNOWN case nkf_ret when 0 k_code = NKF::SJIS when 1 k_code = NKF::EUC when 2 k_code = NKF::JIS when 3 k_code = NKF::UTF8 when 4, 5 k_code = NKF::UTF16 else k_code = NKF::UNKNOWN end k_code end module_function :guess2 alias_method :guess, :guess2 module_function :guess # alias_method :guess1, :guess2 # module_function :guess1 end
この実装では
$KCODE="SJIS"
を設定しています。
他の個所で別の指定が必要な場合にはご注意ください。
都合が悪い場合にはメソッドの中でその時の$KCODEの値をコピーしておいて"SJIS"をセットしてから処理を行って、メソッドを抜けるときに元に戻すなどにする方が良いかもしれません。
例えば
def nkf(opt, str) kcode_copy = $KCODE $KCODE = "SJIS" @@SetNkfOption.call opt ret = "\x00" * (str.size * 3 + 10) ret_len = "\x00\x00\x00\x00" @@NkfConvertSafe.call ret, ret.GetByteCount, ret_len, str, str.GetByteCount ret_len = ret_len[0] + ret_len[1] * 0x100 + ret_len[2] * 0x10000 + ret_len[3] * 0x1000000 $KCODE = kcode_copy ret[0..ret_len-1] end
こんな感じです。
なおこの$KCODE="SJIS"とする理由なのですが、IronRubyではこの$KCODEの指定による動作が怪しいです。
実際に上記のスクリプトでは$KCODE="SJIS"を指定しないと期待するよう結果が得られません。
おそらく$KCODE="NONE"の場合にも文字列が意図せずに文字コード変換が行われているのではないかと思われます。
あともうひとつの注意点として上記の実装では#guess1がコメントアウトされています。
#guess1が使用される場合でとりあえず#guess2と同じ動作で良ければ
# alias_method :guess1, :guess2 # module_function :guess1
この2行のコメントをはずせばよいでしょう。
3.上記実装の利用
module NKFおよびmodule Kconvを使用する前に上記の実装ファイルをrequireしてください。
例えば
require 'ironnkf'
等とします。
これでNKF#nkf、NKF#guess、Kconv#kconv、Kconv#isXXX、Kconv#toXXX等の主要な機能が利用できます。
他のライブラリなどで内部的にmodule NKFおよびmodule Kconv等を使用している場合にもそれらのライブラリを読み込む前にこの実装をrequireすれば大丈夫です。
4.その他、補足
上記内容の品質を保証するつもりはないので十分に確認できているわけではありませんが主な機能は利用できると思います。
制限事項として認識している点は以下の通りです。
2010/10/15修正
みーすけさんのコメントの指摘内容を反映してコードを修正。