我正在尝试编写一个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之类的选项?我找不到任何官方的东西。
1条答案
按热度按时间jgwigjjp1#
这是一个堆栈bug。GHCi需要将任何独立的外部
.o
文件作为参数传递到命令行。Stack检查Cabalc-sources
以确定要提供的C.o
文件的适当列表,但它不检查cxx-sources
行。有几个可能的变通方法。
首先,你可以尝试自己传递正确的文件名,如下所示:
其次,可以考虑在
c-sources
行而不是cxx-sources
行中指定C源代码。Stack和Cabal可以很好地处理c-sources
中列出的C和C文件,它们可以根据文件扩展名正确地识别哪个是哪个。首先,使用cxx-sources
字段的唯一原因是允许不同的cc-options
和cxx-options
字段,以便C和C++文件可以使用不同的标志编译(请参阅cxx-sources的文档)。