Foreign Function Interface (FFI) 如何与 Stack 一起使用?

4
我正在学习一些关于FFI的教程和示例(这里这里),我想知道在使用stack时应该做哪些更改?
在这些示例中,源C文件使用gcc -c -o termops.o termops.c编译为对象文件,并在gcc编译时使用ghc --make -main-is FfiEx -o ffi_ex FfiEx.hs termops.o进行包含。如何使用stack完成相同的操作呢?

1
栈不是正确的组件 - Cabal 是。Stack 是一个帮助解决依赖关系的工具,而 Cabal 则描述了如何构建项目。 - Alec
2
我从来没有直接使用过 Cabal 。我直接使用 Stack 。Stack 不是可以做 Cabal 所能做的一切吗? - user668074
不完全正确。Stack旨在补充Cabal,而不是取代它。在内部,Stack在很大程度上依赖于Cabal。 - Alec
1
那么没有办法运行 stack build 并使用 FFI 进行编译吗? - user668074
2
我没有说过那个。但是让 Stack 构建 FFI 项目的工作发生在 .cabal 文件中,而不是 .stack 文件中。我已经发布了一个示例项目。 - Alec
1个回答

8
这是我能想到的最简化的FFI C项目。
$ cd c-proj
c-proj$ ls
Main.hs      c-proj.cabal c_file.c

这些文件的内容:
  • c-proj.cabal: describes the

    name:            c-proj
    version:         0.1.0.0
    cabal-version:   >= 1.22
    build-type:      Simple
    
    executable main
      main-is:       Main.hs
      build-depends: base >= 4.9
      c-sources:     c_file.c
    
  • Main.hs: the only Haskell source file

    {-# LANGUAGE ForeignFunctionInterface #-}
    
    module Main where
    
    foreign import ccall "plus_ten" plusTen :: Int -> IO Int
    
    main = do
      n <- plusTen 2
      print n
    
  • c_file.c: the C source file

    #include<stdio.h>
    
    int plus_ten(int n) {
      printf("%d + 10\n", n);
      return n + 10;
    }
    
然后,如果你想使用Stack,你可以运行stack init
$ stack init
<< Shell output snipped >>
$ stack build
<< Shell output snipped >>
$ stack exec main
2 + 10
12

1
好的,这就是我一直在寻找的。尤其是c源代码部分似乎是我所缺少的。接下来的问题是:有没有办法使用目标代码文件来代替c源文件?(File.o代替File.c) - user668074
2
当然可以!在executable main下添加以下条目:extra-lib-dirs: "."extra-libraries: File.o - Alec
2
只是挑剔一下:你可以更加简洁。只需在 c-proj.cabal 的开头添加 "build-type: Simple" 并且摆脱 Setup.hs 即可。 - typetetris
@Krom 这可不是小问题!太方便了。我简直不敢相信我一直在用(几乎总是)毫无意义的 Setup.hs 文件污染我的项目! - Alec

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