使用Cabal从C语言调用Haskell

13

我无法弄清如何构建一个调用Haskell Foreign Function Interface的C SDL应用程序,我的主要代码是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

P.S:

  • 我正在使用Ubuntu 18.04进行开发。
  • GHC版本为8.0.2。
  • Cabal版本为1.24.0.2。

4
感谢您提供了一个写得很好的问题和一个良好的 [MCVE]。 - Basile Starynkevitch
1
顺便说一句,我认为在cabal文件中应该是main-is: AI.hs而不是AI.h - chi
我的错,应该是A.hs,这是一个复制粘贴错误,我已经更新了问题。 - Yan.F
你使用哪个编译器来编译.c文件,以及你给它什么参数? - Geraint Ballinger
@Geraint Ballinger gcc编译器,标志:sdl2-config --libs --cflags -ggdb3 -O0 --std=c99 -lSDL2_image -lm -Wall - Yan.F
2个回答

2

HsFFI.h位于您的Haskell安装文件夹中。我正在使用Windows,它位于C:\Program Files\Haskell Platform\8.4.3\lib\include

另外,在构建Haskell模块时,会生成一个.a文件。在我的机器上,它被称为HSdll.dll.a。(我必须将其重命名为HSdll.a以满足gcc的要求,但我认为这应该是一个特定于Windows的问题)

然后,以下命令将起作用:

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

注意:将-I更改为您的Haskell include文件夹,将-L.更改为.a文件所在的位置。


1
这对我很有帮助,但我使用了 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 是我的 C 源代码目录。
  • src/haskell 是我的 Haskell 源代码目录。
  • tmp 是我的对象文件文件夹(所有 *.o 文件)。

虽然我不知道如何使用 cabal 构建包括 C 源代码在内的整个项目。


你在原始问题中指示 GHC 将 Haskell 代码编译为动态共享库,但在这个答案中没有这样做,有什么原因吗? - Geraint Ballinger
@GeraintBallinger 我在使用生成的库时遇到了麻烦,也许我会再试一次。 - Yan.F

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接