wvogel日記

自分用の技術備忘録が多めです.

FFI 2

職場にHaskellを導入する言いながら、
なかなかさせてもらえません。

そろそろこちらからアピールしておかなければ。

今アンとして出ているのは、
パーサーをHaskellで書いてC#などから利用することとか。
C#にもF#にも、ParseqとかFParsecとかあるので
そこまでして頑張る必要も感じなくなってきましたが笑

でもまあ、基本型以外の、
代数的データ型とかもそろそろFFIできるようになっておくと
後々困らなさそう、ということで。

独自データ型をCから使う実験

簡単に、次のような型を定義しました

data Token = Play Int | Repeat Int | Stop
type Commands = [Token]

曲リストがあったとして、そのi番目の要素の操作を仮定

入力されるコマンドは、パーサー書くほどではないので、
次のような入力に対してHaskell側で操作を行います。
"play 8"
"repeat 3"
"stop"

Cから利用できる関数として次を定義。

hGetCommands :: CString -> IO (StablePtr Commands)
hTakeToken :: StablePtr Commands -> Int -> IO (StablePtr Token)
hIsStop :: StablePtr Token -> IO Int
hIsPlay :: StablePtr Token -> IO Int
hIsRepeat :: StablePtr Token -> IO Int

Haskellコードの全容はこちら

そして、それを呼び出す側のCコードはこちら

で、

ghc --make -no-hs-main FFI.hs main.c

としてコンパイル、吐き出された実行ファイルを走らせると、

playing number is (36)

となり、ちゃんと値を取得できました。

自前の型に対して操作を行うときは
C#でいうところのプロパティを
ちゃんと用意してやらないといけないので
面倒といえば面倒ですね