Вызов Хаскеля из Си с Кабалой

Я не могу понять, как создать приложение C SDL, которое вызывает Haskell с иностранным интерфейсом функций, мой главный находится в C, вот мой файл .cabal:

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

Я следовал инструкциям в этой ссылке безуспешно (это для OSX, а не для Linux). Я получаю исходный код на Haskell для успешной сборки:

cabal install

Но я не могу понять, как построить код C таким образом, чтобы Haskell был распознан и импортирован в C. Вот пример моих исходников на C и Haskell:

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

PS:

  • Я развиваюсь в Ubuntu 18.04.
  • Версия GHC - 8.0.2.
  • Кабал версия 1.24.0.2.

Ответы

Ответ 1

HsFFI.h находится в вашей папке установки Haskell. Я использую Windows, и она находится в C:\Program Files\Haskell Platform\8.4.3\lib\include.

Кроме того, при сборке модуля Haskell должен быть создан файл .a. На моей машине это называется HSdll.dll.a. (Я должен переименовать его в HSdll.a, чтобы удовлетворить требования gcc, но я думаю, что это должно быть HSdll.a с Windows.)

Тогда будет работать следующая команда:

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

Примечание: измените -I на вашу папку включения в haskell и -L. к месту, где находится .a файл.

Ответ 2

Это сработало для меня, но я использовал GHC вместо Cabal:

(следуя этому примеру)

Сначала я скомпилировал свою библиотеку на Haskell:

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

Затем я скомпилировал с 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

Куда:

  • src/c - мой каталог с исходниками.
  • src/haskell - это мой исходный каталог на Haskell.
  • tmp Моя папка объектных файлов (все файлы *.o).

Хотя я понятия не имею, как построить весь проект, включая c исходные тексты, с Cabal.