I’ve finally found some time to play with c2hs again. This time I had a quick look at passing pointers to C functions. Here’s what I found, in a rather short format:
{# fun foo { alloca- `Int' peekIntConv* } -> `()' #} => foo :: IO Int
{# fun foo { `Int' peekIntConv* } -> `()' #} => foo :: Int -> IO Int
That is, the former is an out argumenti while the latter is an inout argument.
A C function like this:
int foo(int *);
which is defined like this in haskell
{# fun foo { `Int' peekIntConv* } -> `Int' #}
will return a tuple of two integers, the first one is the returned value from foo the other is the inout argument to foo.
This means that it’s fairly simple to deal with APIs that follow the convention that functions return an error code and that the last argument is the actual result of the function.
A few days ago I thougth I’d take a look at calling C functions from haskell. I wrote up the following set of files:
foo.h:
int foo(int i);
foo.c:
int
foo(int i)
{
return i * i;
}
Foo.hs:
module Main where
import Foreign.C.Types
main = do
r <- foo 2
putStrLn $ show r
foreign import ccall safe "foo.h foo" foo :: CInt -> IO CInt
Compiling the C file was of course no problem:
% gcc -c foo.c
The haskell file offered some resistance:
% ghc -c Foo.hs
Foo.hs:9:8: parse error on input `import'
It took me a round on haskell-cafe before I found out that ghc needs to be told to use the foreign function interface, -ffi or -fffi:
% ghc -c -fffi Foo.hs
Linking is a snap after that:
% ghc -o foo foo.o Foo.o
% ./foo
4
It’s also possible to build and link it all in one go:
% ghc --make -fffi -o foo foo.c Foo.hs
Now, that’s pretty nice, however it’d be even nicer to use cabal to do the building. At the same time I decided to put c2hs to use. It seemed to be a lot easier than having to create the import statements manually. I ended up with the following:
csrc/foo.h:
#ifndef _FOO_H_
int foo(int);
#endif
csrc/foo.c:
#include "foo.h"
int
foo(int i)
{
return i * i;
}
I couldn’t get cabal to accept Foo.chs as the file containing the Main module in my project. So I ended up putting all the relevant code in Foo and then have a dummy Main.
src/Foo.chs:
module Foo where
#include "foo.h"
import Foreign.C.Types
main = do
r <- {# call foo #} 2
putStrLn $ show r
Here’s the dummy Main.
src/Main.hs:
module Main where
import qualified Foo
main = Foo.main
The cabal file is rather straight forward. It took me a round on haskell-cafe to find out how to let the compiler know that I need the foreign function interface without putting compiler directives in the source file.