Haskell 堆栈 C++ 链接失败

问题描述 投票:0回答:1

我正在尝试编写 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

每当我调用 SNF.hs 中定义的函数

cSmithNormalForm
时:

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 文件保持不变。 SNF.hs 和 snf.cpp 都位于同一目录(src)中。

尽管出现错误,

stack build
仍成功运行。

有没有办法修复错误并成功从 Haskell 调用 c++ 函数?另外,是否有任何可用的文档说明如何将 cxx-options 等选项与堆栈一起使用?我找不到任何官方的东西。

c++ haskell haskell-stack
1个回答
0
投票

这是一个堆栈错误。 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-options
cxx-options
字段,以便可以使用不同的标志编译 C 和 C++ 文件(请参阅 cxx-sources 文档)。

© www.soinside.com 2019 - 2024. All rights reserved.