Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Haskell from C with Cabal

Tags:

c

haskell

cabal

I can't figure out how to build a C SDL application that calling Haskell with Foreign Function Interface, my main is in C, here is my .cabal file:

build-type:          Simple
extra-source-files:  README.md
cabal-version:       >=1.10

library
  exposed-modules:     AI     

  other-extensions:    ForeignFunctionInterface
  build-depends:       base >=4.9 && <4.10
  hs-source-dirs:      src/haskell
  default-language:    Haskell2010
  ghc-options:         -O2 -shared -fPIC -dynamic 
  extra-libraries:     HSrts-ghc8.0.2

I followed the instructions in this link with no success(it's for OSX, not Linux). I'm getting the Haskell source to build successfully with:

cabal install

But I can't figure out how to build the C code in such manner that Haskell will be recognized and imported into C. Here is an example of my C and Haskell sources:

main.c:

#include <stdio.h>
#include "game.h"
#include <SDL2/SDL.h>
#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_error.h>
#include "HsFFI.h" // include path not recognized
#include "AI_stub.h" // new! edited

int main( int argc, char** argv ) {
    hs_init(&argc, &argv);
    //HASKELL CALL
    int i;
    i = fibonacci_hs(42);
    printf("Fibonacci: %d\n", i);
    //END HASKELL CALL
    initializeSdl();
    window = createWindow(SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
    renderer = createRenderer();
    printf("Pre gameLoop\n"); 
    play();
    return 0;
}

AI.hs:

{-# OPTIONS_GHC -Wall                 #-}
{-# LANGUAGE ForeignFunctionInterface #-}

module AI 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

P.S:

  • I am developing in ubuntu 18.04.
  • GHC version is 8.0.2.
  • Cabal version is 1.24.0.2.
like image 632
Yan.F Avatar asked Jan 17 '19 20:01

Yan.F


2 Answers

HsFFI.h is located in your Haskell installation folder. I'm using Windows and it is at C:\Program Files\Haskell Platform\8.4.3\lib\include.

Also, when you build your Haskell module, a .a file should be generated. On my machine it is called HSdll.dll.a. (I have to rename it to HSdll.a in order to satisfy gcc, but I think it should be a Windows-specific issue.)

Then the following command will work:

gcc -I"C:\Program Files\Haskell Platform\8.4.3\lib\include" -L. -lHSdll main.c

Note: change the -I to your haskell include folder and -L. to the place where the .a file is.

like image 170
dontpanic Avatar answered Sep 30 '22 14:09

dontpanic


This has worked for me but I used GHC instead of cabal:

(following this example)

First I compiled my Haskell library:

ghc -c -O src/haskell/** -outputdir tmp

Then I compiled with GHC:

ghc --make `sdl2-config --libs --cflags` -optc-O src/c/*.c src/haskell/*.hs -no-hs-main -outputdir tmp -lSDL2_image -o targetLinux/myExecutable

Where:

  • src/c Is my c sources directory.
  • src/haskell Is my Haskell sources directory.
  • tmp Is my object files folder (all of *.o files).

Although I have no clue how to build the entire project including c sources with cabal.

like image 26
Yan.F Avatar answered Sep 30 '22 15:09

Yan.F