Difference between revisions of "FFI Introduction"
Jump to navigation
Jump to search
(Remove section (merged into [Foreign Function Interface (FFI)]) |
(Remove section: will cover this in the new page) |
||
Line 5: | Line 5: | ||
== Compiling FFI-using modules == |
== Compiling FFI-using modules == |
||
− | |||
− | === GHC === |
||
− | |||
− | Here's a makefile fragment to compile an FfiExample module that uses C functions from c_functions.c, which uses library functions from libcfuncs: |
||
− | |||
− | <pre> |
||
− | HFLAGS=-I/path/to/lib/include -L/path/to/lib |
||
− | |||
− | _dummy_target: c_functions.o c_functions.h |
||
− | ghc $(HFLAGS) -main-is FfiExample --make -o ffi_example c_functions.o -lcfuncs |
||
− | </pre> |
||
− | |||
− | Notice the use of _dummy_target and --make. The idea is that you get make to compile what is necessary for C, and then always run ghc with --make, at which point it will figure out what is necessary to compile for Haskell. |
||
− | |||
− | Actually, this is broken, because ghc --make will not notice if a .o file has changed! |
||
− | |||
− | [ ''this is just my hack, anyone have a better way to do this?'' ] |
||
== Complete example with GHC == |
== Complete example with GHC == |
Revision as of 13:25, 16 February 2015
Haskell's FFI is used to call functions from other languages (basically C at this point), and for C to call Haskell functions.
Compiling FFI-using modules
Complete example with GHC
GHC's libs don't (apparently?) support generic termios stuff. I could implement the whole tcgetattr / tcsetattr thing, but let's just turn ICANON on and off, so IO.getChar doesn't wait for a newline:
termops.c:
#include <termios.h> #include "termops.h" void set_icanon(int fd) { struct termios term; tcgetattr(0, &term); term.c_lflag |= ICANON; tcsetattr(fd, TCSAFLUSH, &term); } void unset_icanon(int fd) { struct termios term; tcgetattr(0, &term); term.c_lflag &= ~ICANON; tcsetattr(fd, TCSAFLUSH, &term); }
termops.h:
void set_icanon(int fd); void unset_icanon(int fd);
Termios.hs:
{-# INCLUDE <termios.h> #-}
{-# INCLUDE "termops.h" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
module Termios where
import Foreign.C
foreign import ccall "set_icanon" set_icanon :: CInt -> IO ()
foreign import ccall "unset_icanon" unset_icanon :: CInt -> IO ()
FfiEx.hs:
module FfiEx where
import Control.Exception
import System.IO
import qualified Termios
import Control.Monad (when)
main = bracket_ (Termios.unset_icanon 0) (Termios.set_icanon 0)
(while_true prompt)
while_true op = do
continue <- op
when continue (while_true op)
prompt = do
putStr "? "
hFlush stdout
c <- getChar
putStrLn $ "you typed " ++ [c]
return (c /= 'q')
makefile:
_ffi_ex: termops.o ghc --make -main-is FfiEx -o ffi_ex FfiEx.hs termops.o
[this only worked for me when I omitted termops.o at the end of the `ghc --make` command. Seems like it searches for and finds the .o automatically? --lodi ]
And now:
% make gcc -c -o termops.o termops.c ghc --make -main-is FfiEx -o ffi_ex FfiEx.hs termops.o [1 of 2] Compiling Termios ( Termios.hs, Termios.o ) [2 of 2] Compiling FfiEx ( FfiEx.hs, FfiEx.o ) Linking ffi_ex ... % ./ffi_ex ? you typed a ? you typed b ? you typed q %