Windows 環境の Haskell に iconv パッケージをインストール

以下の環境の Haskell文字コード変換のための iconv パッケージをインストールする手順を書いておきます。

  • HaskellPlatform 2010.2.0.0 (GHC 6.10.4)

今回、FFI(外部関数インターフェース)を使っているパッケージのインストールが初めてで勝手が分からず苦労しましたが、以下のサイトが非常に参考になりました。

なお、iconv.h ファイル等を用意して cabal コマンドでインストールしてみると、インストールは一応完了しますが、実行時にエラーが出るようなのでご注意ください。(手動でインストールするしかないみたいです)

事前準備

まず、以下のサイトから iconv-0.4.0.2.tar.gz をダウンロードして適当なディレクトリに解凍しておきます。

次に、iconv.dll 等を入手して libiconv.a ファイルを作成する事になりますが、Mono 2.8 のインストール先に必要なファイルが全部あったので今回はそれを使う事にしました。

手順は以下の通りです。

  • Mono の bin\iconv.dll ファイルを Haskellmingw\bin にコピー
  • Mono の include\iconv.h ファイルを Haskellmingw\include にコピー
  • Mono の lib\libiconv.a ファイルを Haskellmingw\lib にコピー

ソースの編集

解凍した iconv パッケージのソースファイルを編集します。

まず、Codec\Text\IConv.hs ファイルの Control.Exception の import 箇所を Control.OldExcepion に置換します。
(例 xxx.Exception -> xxx.OldException)

Codec\Text\IConv.hs 修正後 (56行目付近)
import Control.OldException (assert)
import qualified Control.OldException as Exception

次に、Codec\Text\IConv\Internal.hs ファイルの FFI で参照する 3つの関数(iconv_open, iconv, iconv_close)の名前の先頭に lib を付けます。
(例 iconv_open -> libiconv_open)

Codec\Text\IConv\Internal.hs 修正後 (371行目付近)
foreign import ccall unsafe "iconv.h libiconv_open"
・・・
foreign import ccall unsafe "iconv.h libiconv"
・・・
foreign import ccall unsafe "iconv.h &libiconv_close"
・・・

ビルドとインストール

iconv パッケージの解凍先ディレクトリで Setup.hs の configure/build/install を実行してインストールを行います。(Warning は無視)

以下の例では、cabal を使った際のデフォルトインストール先(%APPDATA%\cabal)にパッケージをインストールするため --user オプションを指定しています。(何も指定しないと Program Files へインストールする設定になり都合が悪い)

ビルドとインストール実行例
> runhaskell Setup.hs configure --user
・・・
> runhaskell Setup.hs build
・・・
> runhaskell Setup.hs install
・・・
Registering iconv-0.4.0.2...

動作確認

以下のようなソースコードUTF-8 で保存)を使って動作確認してみます。

to_sjis.hs(UTF-8
import Codec.Text.IConv (convert)
import Codec.Binary.UTF8.String (encodeString)
import qualified Data.ByteString.Lazy.Char8 as C

main = do
    let msg = "UTF-8 から Shift_JIS への文字コード変換テスト"
    -- 内部文字を encodeString で UTF-8 化してから Shift_JIS に変換
    let sjisMsg = C.unpack $ convert "UTF-8" "Shift_JIS" $ C.pack $ encodeString msg
    
    -- UTF-8 で出力
    putStrLn $ encodeString msg
    -- Shift_JIS で出力
    putStrLn sjisMsg

オプションに -liconv を指定して実行すれば、2行目が Shift_JIS に変換されて出力されるはずです。(オプションを指定しないとエラーが発生します)

実行例
> runhaskell -liconv to_sjis.hs
UTF-8 ・・・
UTF-8 から Shift_JIS への文字コード変換テスト

ソースは http://github.com/fits/try_samples/tree/master/blog/20101105/