Difference between revisions of "Calling Haskell from C"
Jump to navigation
Jump to search
(fix filenames; one more standard #include; update to a GHC need (hs_add_root); another compile command) |
(Remove unneeded code indentation) |
||
Line 5: | Line 5: | ||
<haskell> |
<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 |
|
</haskell> |
</haskell> |
||
Line 26: | Line 26: | ||
And call it from C: |
And call it from C: |
||
⚫ | |||
− | <haskell> |
||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
+ | |||
⚫ | |||
⚫ | |||
− | |||
+ | { |
||
⚫ | |||
− | + | 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; |
|
+ | } |
||
− | } |
||
− | </haskell> |
||
Now, first compile the Haskell file: |
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 |
Which creates Safe_stub.c, Safe_stub.o, Safe_stub.h, which you import into |
||
Line 57: | Line 56: | ||
the Haskell objects on the command line: |
the Haskell objects on the command line: |
||
− | + | $ ghc -optc-O test.c Safe.o Safe_stub.o -o test |
|
− | |||
− | (Alternatively, fewer files to enumerate: |
||
− | + | (Alternatively, fewer files to enumerate: <code>ghc --make -no-hs-main -optc-O test.c Safe -o test</code>) |
|
− | ) |
||
Then run your C code: |
Then run your C code: |
||
− | + | $ ./test |
|
− | + | Fibonacci: 267914296 |
|
And that's it. |
And that's it. |
Revision as of 09:48, 5 March 2012
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.