Haskell堆栈C++链接失败

w3nuxt5m  于 9个月前  发布在  其他
关注(0)|答案(1)|浏览(59)

我正在尝试编写一个Haskell库,并在堆栈ghci中得到错误消息:

ghci> functionThatCalls_cSmithNormalForm 0
ghc-9.4.5: ^^ Could not load 'csmith_normal_form', dependency unresolved. See top entry above.

GHC.ByteCode.Linker: can't find label
During interactive linking, GHCi couldn't find the following symbol:
  csmith_normal_form

每当我调用函数cSmithNormalForm时,它在SNF.hs中定义为:

foreign import ccall "csmith_normal_form" cSmithNormalForm :: Ptr CLLong -> IO (Ptr CLLong)

C函数在snf.cpp文件(整个项目中唯一的c文件)中导出为:

using i64 = long long;
(...)
extern "C" {
    i64 *csmith_normal_form(i64[]);

    i64 *csmith_normal_form(i64 _mx[]) {
        (...)
    }
}

经过多次尝试建立此链接后,我的package.yaml文件包含以下内容:

cxx-sources:
- src/snf.cpp
cxx-options:
- -std=c++17

include-dirs:
- src

library:
  source-dirs: src
  cxx-sources:
  - src/snf.cpp
  cxx-options:
  - -std=c++17
  when:
    - condition: os(linux)
      extra-libraries: stdc++

stack.yaml文件保持不变。hs和snf.cpp都位于同一个目录(src)中。
尽管出现错误,stack build仍能成功运行。
有没有一种方法可以修复错误并成功地从Haskell调用c++函数?另外,是否有任何可用的文档来说明如何在堆栈中使用cxx-options之类的选项?我找不到任何官方的东西。

jgwigjjp

jgwigjjp1#

这是一个堆栈bug。GHCi需要将任何独立的外部.o文件作为参数传递到命令行。Stack检查Cabal c-sources以确定要提供的C .o文件的适当列表,但它不检查cxx-sources行。
有几个可能的变通方法。
首先,你可以尝试自己传递正确的文件名,如下所示:

$ stack ghci --ghci-options $(find .stack-work -name 'snf.o')

其次,可以考虑在c-sources行而不是cxx-sources行中指定C源代码。Stack和Cabal可以很好地处理c-sources中列出的C和C文件,它们可以根据文件扩展名正确地识别哪个是哪个。首先,使用cxx-sources字段的唯一原因是允许不同的cc-optionscxx-options字段,以便C和C++文件可以使用不同的标志编译(请参阅cxx-sources的文档)。

相关问题