【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

FFI

Haskellをどこから使い始めれば良いのか分からずに放置していたのですが、何気なく検索したFFIが気になったので遊んでみました。

ghc

今までghciでクイックソートをやって遊んだりしただけで、ghcコンパイルしたことがありませんでした。今回はWindowsghcをInterixから使います。パスを通すのではなく、/usr/local/binにシンボリックリンクを作りました。

% ln -s /dev/fs/C/ghc/ghc-7.0.1/bin/ghc.exe /usr/local/bin/ghc

ハローワールド

FFIを使わない簡単なプログラムをコンパイルしてみます。

test1.hs
main = do putStrLn "hello"

ghcにソースを渡すと、同じ名前のEXE(この場合はtest1.exe)が出てきます。この辺の感覚はcscに似ています。

% ghc test1.hs
[1 of 1] Compiling Main             ( test1.hs, test1.o )
Linking test1.exe ...
% ./test1.exe
hello

FFI(スタティックリンク)

シンプルな例を見つけたので、試してみました。

上の例ではghciから呼び出していますが、C言語Haskellのコードを同時にコンパイルして、1つのEXEに出来ました。ヘッダは省略しても問題ないようです。

hello.c
#include <stdio.h>

void hello() {
	printf("hello ffi\n");
}

Haskellソースの最初の行はC言語の#pragmaディレクティブに相当するようです。foreign importの定義はP/Invokeに似ている印象です。

test2.hs
{-# LANGUAGE ForeignFunctionInterface #-}

import Foreign

foreign import ccall "hello" hello :: IO ()

main = do hello

ghcC言語も受け付けるので、コンパイルはとても簡単です。WindowsC言語コンパイルは、ghcにバンドルされたgccに振られます。

% ghc hello.c test2.hs
[1 of 1] Compiling Main             ( test2.hs, test2.o )
Linking test2.exe ...
% ./test2.exe
hello ffi

こんなに簡単にC言語と組み合わせられるとは思っていなかったので驚きました。

FFI(ダイナミックリンク)

C言語をDLLに分離してリンクするのも簡単でした。ソースは同じです。

% i686-mingw32-gcc -shared -o hello.dll hello.c
% ghc test2.hs hello.dll
Linking test2.exe ...
% ./test2.exe
hello ffi

DLLを消すと起動できなくなるため、リンクされていることが確認できます。

% rm hello.dll
% ./test2.exe
エラー