【问题标题】:Calling Haskell from C with Cabal使用 Cabal 从 C 调用 Haskell
【发布时间】:2019-01-27 02:34:34
【问题描述】:

我不知道如何构建一个使用外部函数接口调用 Haskell 的 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

我按照link 中的说明进行操作,但没有成功(适用于 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。
  • Cabal 版本是 1.24.0.2。

【问题讨论】:

  • 感谢minimal reproducible example写得很好的问题@
  • 顺便说一句,我认为在 cabal 文件中应该是 main-is: AI.hs,而不是 AI.h
  • 我的错是 A.hs 它是复制粘贴错误,我已经更新了问题
  • 您使用哪个编译器来编译.c 文件,您给它提供了哪些参数?
  • @Geraint Ballinger gcc 编译器,标志:sdl2-config --libs --cflags -ggdb3 -O0 --std=c99 -lSDL2_image -lm -Wall

标签: c haskell cabal


【解决方案1】:

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 包含文件夹,将-L. 更改为.a 文件所在的位置。

【讨论】:

    【解决方案2】:

    这对我有用,但我使用 GHC 而不是 cabal:

    (following this example)

    首先我编译了我的 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 代码编译为动态共享库,但在此答案中没有,是否有原因?
    • @GeraintBallinger 我在使用生成的库时遇到了麻烦,也许我会再试一次。
    猜你喜欢
    • 2013-05-13
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 2022-01-17
    • 1970-01-01
    相关资源
    最近更新 更多