[Haskell-cafe] Building shared library to be called from C

Auke Booij auke at tulcod.com
Sat Apr 9 22:58:22 UTC 2016


Hi Jack,

I would be interested in hearing solutions as well.

The missing component is probably the HSrts-ghc library which you need
to link in. Try adding -lHSrts-ghc7.10.3 to your compilation commands.
Note that if you want to use preemptive threading, you should use a
different RTS, hence a different library (though I'm not sure what the
impact of threads launched by C code that calls your Haskell library
is).

I think the easiest way to set this up is using a cabal project
structure. See, for example:

https://github.com/nh2/call-haskell-from-anything
https://github.com/abooij/sudbury
https://github.com/ShabbyX/libpandoc

Unfortunately, this is a bit of a hack, and in particular will not be
able to install your .so library file in the correct location. (and
forget about the version symlinks) And depending on other libraries
(e.g. HSinteger-gmp for the integer-gmp package) is prone to breakage
as the library name changes per build. (unless there is a smarter way
to do this, which is why I would be interested in further replies)

It looks like the cabal developers are also working on this:

https://github.com/haskell/cabal/issues/141
https://github.com/haskell/cabal/pull/2540

Best of luck,
Auke.

On 7 April 2016 at 17:52, Jack Hill <jackhill at jackhill.us> wrote:
> Hi,
>
> I'm attempting to build a shared library that can be called from C. My end
> goal is to build a PAM module, but for now I'm working with toy programs so
> that I can get a feel for building how to build the library.
>
> The Haskell part looks like this (in a file called hfact.hs)
>
>   module Hfact where
>
>   import Foreign
>   import Foreign.C.Types
>
>   foreign export ccall fact_hs :: CInt -> CInt
>
>   fact :: Int -> Int
>   fact x = product [1..x]
>
>   fact_hs :: CInt -> CInt
>   fact_hs = fromIntegral . fact . fromIntegral
>
> I can compile this into a so (I think successfully) with "ghc --make -shared
> -dynamic -fPIC -o libhfact.so hfact.hs".
>
> Now I would like to be able to call this from C. I have a C program (in a
> file called main.c) as follows:
>
>   #include <stdio.h>
>   #include "HsFFI.h"
>   #include "hfact_stub.h"
>
>   int main(int argc, char *argv[]) {
>     int user, answer;
>
>     scanf("%d", &user);
>     hs_init(&argc, &argv);
>     answer = fact_hs(user);
>     hs_exit();
>     printf("Result: %d\n", answer);
>
>     return 0;
>   }
>
> Unfortunately, I'm at a loss for how to build and link this against my so.
>
> If I try "gcc main.c -lhfact", I get many undefined symbol errors like:
>
> /nfshomes/j/jackhill/.stack/programs/x86_64-linux/ghc-7.10.3/lib/ghc-7.10.3/base_HQfYBxpPvuw8OunzQu6JGM/libHSbase-4.8.2.0-HQfYBxpPvuw8OunzQu6JGM-ghc7.10.3.so:
> undefined reference to `__hscore_get_saved_termios'
>
> If I try "ghc maint.c -lhfact" I get:
>
> /tmp/ghc19146_0/ghc_4.o: In function `main':
> ghc_3.c:(.text+0x0): multiple definition of `main'
> maint.o:maint.c:(.text+0x0): first defined here
> /tmp/ghc19146_0/ghc_4.o: In function `main':
> ghc_3.c:(.text+0x61): undefined reference to `ZCMain_main_closure'
> collect2: error: ld returned 1 exit status
>
> How should I be calling Haskell from C?
>
> Best,
> Jack
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list