Haskell FFI Basics
Fraser Tweedale
@hackuador
March 24, 2015
Slide 2
Slide 2 text
Intro
Slide 3
Slide 3 text
This talk
What’s an FFI?
Haskell C FFI
c2hs
Other tools and resources
Slide 4
Slide 4 text
What is an FFI?
Mechanism to call code written in one language from code
written in another language
Often used to bind or wrap an entire library (usually C)
Sometimes used to export routines to be called from other
language
Slide 5
Slide 5 text
C - important aspects
Header files (*.h)
Linking to library object code
Pointers
Oh my God, it’s full of stars!
Haskell FFI - safe and unsafe
safe is required when foreign function can call back into
Haskell runtime
safe is recommended when foreign function could block
safe has performance penalties
safe is the default
Slide 9
Slide 9 text
Haskell FFI - pointers
int thing_get_version(thing_t *thing);
char *thing_get_name(thing_t *thing);
int thing_new(char *name, thing_t **p);
void thing_free(thing_t *thing);
Haskell FFI - pointers
withCString :: String -> (CString -> IO a) -> IO a
peekCString :: CString -> IO String
peek :: Ptr a -> IO a
alloca :: Storable a => (Ptr a -> IO b) -> IO b
Slide 12
Slide 12 text
Haskell FFI - pointers
newtype Thing = Thing (Ptr Thing)
makeThing :: String -> IO (Maybe Thing)
makeThing s =
withCString s $ \name ->
alloca $ \ptr -> do
result <- thing_new name ptr
if result == 0
then Just . Thing <$> peek ptr
else return Nothing
Slide 13
Slide 13 text
Haskell FFI - garbage collection
type FinalizerPtr a = FunPtr (Ptr a -> IO ())
newForeignPtr
:: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
addForeignPtrFinalizer
:: FinalizerPtr a -> ForeignPtr a -> IO ()
withForeignPtr
:: ForeignPtr a -> (Ptr a -> IO b) -> IO b
Slide 14
Slide 14 text
Haskell FFI - garbage collection
foreign import ccall "&thing_free"
thing_free :: FinalizerPtr a
newtype Thing = Thing (FinalizerPtr Thing)
makeThing :: String -> IO (Maybe Thing)
makeThing s =
withCString s $ \name ->
alloca $ \ptr -> do
result <- thing_new name ptr
if result == 0
then Just . Thing . newForeignPtr thing_free
<$> peek ptr
else return Nothing
Slide 15
Slide 15 text
Haskell FFI - Storable
class Storable a where
sizeOf :: a -> Int
alignment :: a -> Int
peek :: Ptr a -> IO a
poke :: Ptr a -> a -> IO ()
Slide 16
Slide 16 text
c2hs
Slide 17
Slide 17 text
c2hs
Preprocessor to simplify bindings
Enums and typedefs
Automatic foreign import (demand-based)
*.chs file extensions; outputs *.hs
Slide 18
Slide 18 text
Detour: notmuch
Mail indexer
Written in C++ (exports C interface)
I have written a binding (immature)
c2hs
{#context prefix = "notmuch" #}
Finalisers must be manually attached (use
addForeignPtrFinalizer)
pointer directive without newtype makes type synonym
hsc2hs
*.hsc (compare *.chs)
Can bind to #define, e.g. macros, constants
Better Storable boilerplate automation
Otherwise, c2hs is more powerful
Discussion of differences (Stack Overflow):
http://is.gd/weyuYN
Slide 28
Slide 28 text
More tools
c2hsc
.h -> .hcs, .hsc.helper.c
bindings-DSL
CPP macros to help write bindings
language-c-inline
Inline C and Objective C via TH
https:
//github.com/mchakravarty/language-c-inline/
Slide 29
Slide 29 text
Conclusion
Slide 30
Slide 30 text
What we covered
FFI - what and why?
Direct C FFI usage
c2hs examples
Overview of other tools
You can write a binding now!
Slide 31
Slide 31 text
What we didn’t cover
Calling Haskell from C (foreign export)
Dealing with external GCs, “special” allocators
Storable typeclass
hsc2hs or other tools in any detail
Other Haskell FFIs (e.g. JavaScriptFFI)
Fin
Copyright 2015 Fraser Tweedale
This work is licensed under the Creative Commons Attribution 4.0
International License. To view a copy of this license, visit
http://creativecommons.org/licenses/by/4.0/.
Slides https://github.com/frasertweedale/talks/
Email [email protected]
Twitter @hackuador