椿の日記

たぶんプログラムの話をします

DLLをHaskellで使う

以前Haskellでiconvでもiconv.dllを使いましたが、今度は自分でDLLを作ってFFIを利用して呼び出してみます。

DLLを作る

自分は、普段はVisualStudioを使ってるので、VS2010でDLLを構築します。
とりあえずWin32プロジェクトでDLLを選択して、以下のような関数を追加します。

dllsample.cpp
extern "C" int SampleFunction( int v1, int v2 )
{
	return v1 * v2;
}

定義ファイルも追加します。
リンカの設定でモジュールの定義ファイルの項目に加えるのを忘れずに。

dllsample.def
LIBRARY   DLLSAMPLE
EXPORTS
   SampleFunction

ghc用のリンク用ライブラリを構築する

(gccでコンパイルするときは多分不要な項目だと思います)
VisualStudioでDLLを構築すると、インポートライブラリとして.libが構築されます。
しかし、.libはghcではリンクできません。
dlltoolを使って、.defファイルから、.aファイルを構築します。

$ dlltool -d dllexport.def -l libdllsample.dll.a

dlltoolはmingwに入っています。mingwはghcのフォルダの中に入ってるので、それを使えばよいでしょう。
(例えば C:\usr\bin\ghc\ghc-6.12.3\mingw\bin とかにあります)

Haskellから呼び出すコードを書く

dllsample.hs
{-# LANGUAGE ForeignFunctionInterface #-}

foreign import ccall "SampleFunction" c_SampleFunction :: Int -> Int -> Int

main :: IO ()
main = print $ c_SampleFunction 100 200

ビルドと確認

$ ghc --make dllsample.hs libdllsample.dll.a
Linking dllsample.exe ...

$ dllsample
20000

実に簡単ですなあ。