Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GHC/FFI: calling haskell module which imports haskell libraries from C

Let's take a common example how a haskell function can be called from a C function:

Haskell module:

{-# 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

And C module:

#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;
}

I compile and link it:

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

That's ok. But what if I need to import some library in haskell module? E.g., if I need to use bytestrings I should add "import Data.Bytestring.Char8" (this module is taken for an example and is not used in code):

{-# LANGUAGE ForeignFunctionInterface #-}

module Safe where

import Foreign.C.Types
import Data.Bytestring.Char8

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

And that's not ok, for now I get an error:

$ ...undefined reference to `__stginit_bytestringzm0zi9zi2zi0_DataziByteStringziChar8_'

All I've currently found on the problem is this: a bug in GHC and as follows changeset (more formal description of the bug)

As I use ghc-6.12.3, I already have this feature implemented. So I have no idea how to fix the problem.

Perhaps, it would be easier to make a shared library and dynamically link it with my C module?

like image 952
skvadrik Avatar asked Jan 11 '12 15:01

skvadrik


1 Answers

I don't think that bug is related. Have you tried using --make?

$ ghc -c -O Safe.hs
$ ghc --make test.c Safe.o Safe_stub.o -o test

Those errors are the kinds of errors you used to get1 when linking pure-Haskell code with package dependencies without using --make; GHC links in base by default, but if you want anything from another package that doesn't work.

You could also try specifying the packages explicitly if you want a more "manual" method:

$ ghc -c -O Safe.hs
$ ghc -package bytestring test.c Safe.o Safe_stub.o -o test

1 Since GHC 7, --make has been the default.

like image 87
ehird Avatar answered Oct 25 '22 04:10

ehird