Ru/FFI Introduction
FFI используется для вызова функций из других языков программирования (здесь, в основном, рассматривается C) и для вызова функций Haskell из программ на C.
Ссылки
- Официальное описание FFI
- FFICookBook -- много полезных примеров.
Краткий пример
В FFICookBook приведено много хороших примеров, но вот один из базовых:
{-# INCLUDE <math.h> #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module FfiExample where
import Foreign.C -- get the C types
-- pure function
-- "unsafe" means it's slightly faster but can't callback to haskell
foreign import ccall unsafe "sin" c_sin :: CDouble -> CDouble
sin :: Double -> Double
sin d = realToFrac (c_sin (realToFrac d))
Обратите внимание, что в документации к FFI рекомендуется, записывать имя заголовочного файла между двойными кавычками, вот так
foreign import ccall unsafe "math.h sin" c_sin :: CDouble -> CDouble
А вот в GHC документации говорится, что "Правильный Способ" -- использование директив компилятора (может быть по причинам технического характера?), поэтому, обычно, большинство импортов состоит из нескольких заголовочных файлов C (.h), которые прописывают один раз перед кодом на Haskell в самом начале файла.
Следует отметить, что типы C отличаются от типов Haskell, поэтому вы должны импортировать их из модуля Foreign.C.
Notice also that, as usual in haskell, you have to explicitly convert to and from haskell types. Using c_<name_of_c_function> for the raw C function is just my convention.
The haskell report only guarantees that Int has 30 bits of signed precision, so converting CInt to Int is not safe! On the other hand, many classes have instances for Int and Integer but not CInt, so it's generally more convenient to convert from the C types. To convert, I suppose you could either write a checkedFromIntegral function if you're sure it's small or just use Integer.
For details on impure functions, pointers to objects, etc., see the cookbook.