FFI を学ぶ(1) :初めての Foreign Function Interface (FFI)

Haskell からは C の関数が呼べます。

{-# OPTIONS -fglasgow-exts #-}

import Foreign
import Foreign.C.String
import Foreign.C.Types
import System.IO.Unsafe (unsafePerformIO)

foreign import ccall "math.h sin"       c_sin :: Double -> Double
foreign import ccall "string.h strlen"  c_strlen :: CString -> CUInt
-- 同じ printf をHaskellでは2種類定義してみました。
foreign import ccall "stdio.h  printf"  c_printf :: CString -> IO ()
foreign import ccall "stdio.h  printf"  c_print2 :: CString -> Double -> IO ()

main = do

    -- 参考:ホワット・ア・ワンダフル・ワールド :: FFI とか Eval とか
    -- http://alohakun.blog7.fc2.com/blog-entry-657.html
    c_printf $ unsafePerformIO $ newCString "Hello,world!\n" -- => Hello,world!

    -- newCString は解放が必要らしい。
    -- withCString を使うと自動解放してくれるらしい。
    -- 参考:オレのメモ
    -- http://bw28.blog5.fc2.com/?tag=Haskell
    withCString "Hello,world!\n"     c_printf                -- => Hello,world!
    newCString  "Hello,world!\n" >>= c_printf                -- => Hello,world!

    str <- newCString "Hello,world!\n"
    putStrLn $ show $ c_strlen  str                          -- => 13
    putStrLn $ show $ c_sin     40.0                         -- => 0.7451131604793488
    form <- newCString "Sin 40.0 = %f\n"
    c_print2 form (c_sin     40.0)                           -- => Sin 40.0 = 0.745113

Haskell の文字列はListですし、Cの文字列はヌル終端のchar型配列ですから、どうやって値のやりとりをするかという問題があります。
C の関数はreturn で値を返さずにポインタを引数として受け取り文字列や構造体の実態を副作用として処理するものがほとんど。それをラップする関数を書かなくてはならないのかも知れません。