【问题标题】:How is Foreign Function Interface (FFI) used with Stack?堆栈如何使用外部函数接口 (FFI)?
【发布时间】:2017-10-05 02:15:06
【问题描述】:

我正在关注一些 FFI 教程和示例(herehere),我想知道使用堆栈时应该改变什么?

在示例中,源 C 文件使用 gcc -c -o termops.o termops.c 编译为目标文件,并使用 ghc --make -main-is FfiEx -o ffi_ex FfiEx.hs termops.o 包含在 gcc 编译中。使用堆栈如何实现等效?

【问题讨论】:

  • 堆栈不是这个的正确组件 - Cabal 是。 Stack 是一个工具,可帮助您确定如何解决您的依赖关系,而 Cabal 描述如何构建您的项目。
  • 我从来没有真正直接使用过 cabal。我直接去使用堆栈。不能堆栈做阴谋集团可以做的一切吗?
  • 不完全。 Stack 旨在补充 Cabal,而不是取代它。在内部,Stack 相当依赖 Cabal。
  • 所以他们无法运行stack build 并使用 FFI 进行编译?
  • 我没这么说。但是让 Stack 构建 FFI 项目的工作发生在 .cabal 文件中,而不是 .stack 文件中。我已经发布了一个示例项目。

标签: c haskell ffi haskell-stack


【解决方案1】:

这是我所能想象到的最小的 FFI C 项目。

$ cd c-proj
c-proj$ ls
Main.hs      c-proj.cabal c_file.c

这些文件的内容:

  • c-proj.cabal:描述了

    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:唯一的 Haskell 源文件

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

    #include<stdio.h>
    
    int plus_ten(int n) {
      printf("%d + 10\n", n);
      return n + 10;
    }
    

然后,如果你想使用堆栈,你可以运行stack init

$ stack init
<< Shell output snipped >>
$ stack build
<< Shell output snipped >>
$ stack exec main
2 + 10
12

【讨论】:

  • 好的,这就是我要找的。特别是 c-sources 部分似乎是我所缺少的。追问,有没有办法用目标代码文件代替c源文件? (File.o 而不是 File.c)
  • 是的,当然!在 executable main 下,添加以下条目:extra-lib-dirs: "."extra-libraries: File.o
  • 只是吹毛求疵:你可以做得更小。只需将“build-type: Simple”添加到 c-proj.cabal 的开头并删除 Setup.hs。
  • @Krom 一点也不挑剔!这太方便了。我不敢相信我一直在用(几乎总是)毫无意义的 Setup.hs 文件污染我的项目!
猜你喜欢
  • 2020-08-15
  • 2016-07-14
  • 2018-08-20
  • 2019-03-08
  • 2011-02-13
  • 2015-01-26
  • 1970-01-01
  • 2019-11-22
  • 2017-12-06
相关资源
最近更新 更多