Personal tools

Calling Haskell from C

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
m
(fix filenames; one more standard #include; update to a GHC need (hs_add_root); another compile command)
Line 27: Line 27:
  
 
<haskell>
 
<haskell>
     #include "A_stub.h"
+
    #include <HsFFI.h>
 +
    #ifdef __GLASGOW_HASKELL__
 +
     #include "Safe_stub.h"
 +
    extern void __stginit_Safe(void);
 +
    #endif
 
     #include <stdio.h>
 
     #include <stdio.h>
  
Line 33: Line 37:
 
       int i;
 
       int i;
 
       hs_init(&argc, &argv);
 
       hs_init(&argc, &argv);
 +
    #ifdef __GLASGOW_HASKELL__
 +
      hs_add_root(__stginit_Safe);
 +
    #endif
  
 
       i = fibonacci_hs(42);
 
       i = fibonacci_hs(42);
Line 44: Line 51:
 
Now, first compile the Haskell file:
 
Now, first compile the Haskell file:
  
     $ ghc -c -O A.hs
+
     $ ghc -c -O Safe.hs
  
Which creates some *.c and *.h headers, which you import into
+
Which creates Safe_stub.c, Safe_stub.o, Safe_stub.h, which you import into
 
your C program. Now compile your C code with ghc (!), passing
 
your C program. Now compile your C code with ghc (!), passing
 
the Haskell objects on the command line:
 
the Haskell objects on the command line:
  
     $ ghc -optc-O test.c A.o A_stub.o -o test
+
     $ ghc -optc-O test.c Safe.o Safe_stub.o -o test
 +
 
 +
(Alternatively, fewer files to enumerate:
 +
 
 +
    $ ghc --make -no-hs-main -optc-O test.c Safe -o test
 +
)
  
 
Then run your C code:
 
Then run your C code:

Revision as of 03:26, 5 May 2011

It is not uncommon to want to call a Haskell function from C code. Here's how to do that.

We define the fibonacci function in Haskell:

    {-# LANGUAGE ForeignFunctionInterface #-}
 
    module Safe where
 
    import Foreign.C.Types
 
    fibonacci :: Int -> Int
    fibonacci n = fibs !! n
        where fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
 
    fibonacci_hs :: CInt -> CInt
    fibonacci_hs = fromIntegral . fibonacci . fromIntegral
 
    foreign export ccall fibonacci_hs :: CInt -> CInt

Note the foreign export. When GHC sees this, it will generate stubs for C, to help it work out the Haskell types.

And call it from C:

    #include <HsFFI.h>
    #ifdef __GLASGOW_HASKELL__
    #include "Safe_stub.h"
    extern void __stginit_Safe(void);
    #endif
    #include <stdio.h>
 
    int main(int argc, char *argv[]) {
       int i;
       hs_init(&argc, &argv);
    #ifdef __GLASGOW_HASKELL__
       hs_add_root(__stginit_Safe);
    #endif
 
       i = fibonacci_hs(42);
       printf("Fibonacci: %d\n", i);
 
       hs_exit();
       return 0;
    }

Now, first compile the Haskell file:

   $ ghc -c -O Safe.hs

Which creates Safe_stub.c, Safe_stub.o, Safe_stub.h, which you import into your C program. Now compile your C code with ghc (!), passing the Haskell objects on the command line:

   $ ghc -optc-O test.c Safe.o Safe_stub.o -o test

(Alternatively, fewer files to enumerate:

   $ ghc --make -no-hs-main -optc-O test.c Safe -o test

)

Then run your C code:

   $ ./test 
   Fibonacci: 267914296

And that's it.