设置:我有一个Haskell库HLib
,它可以调用C/C++后端CLib
以提高效率。后端很小,专用于HLib
。 CLib
的接口(interface)只能通过HLib
公开; HLib
测试,HLib
基准测试和依赖HLib
的第三方库不会直接对CLib
进行FFI调用。从test/benchmark/3rd party lib的角度来看,HLib
应该纯粹是Haskell出现。这意味着在例如HLib
测试的cabal文件部分中,不应引用-lCLib
,libCLib
等,仅应在build-depends
上引用HLib
,并且可执行文件无需寻找动态CLib
库。我需要能够在HLib
和第三方库中构建和运行所有可执行文件,以及运行cabal repl
进行开发。
最初,CLib
是用纯C语言编写的。Cabal支持这种情况,并且我可以使用cabal文件中的CLib
,HLib
和include-dirs
字段,以上述完全相同的方式将c-sources
集成到includes
中。CLib
已经发展成为一个C++库,我不知道该如何使Cabal轻松集成。相反,我求助于具有自定义build和Setup.hs的makefile,例如this。您可以看到此方法here 1,2的一个小示例。
在该示例中,我无法在cabal repl
中运行HLib
,因为“不支持加载文件”。这确实意味着我需要一个动态的C++库,该库很容易创建(在CLib
makefile中有一条注释行可以做到这一点)。但是,如果我制作了动态C++库,则由于“没有这样的文件或目录libclib.so”,对HLib
的测试在运行时失败了。这很糟糕(除了崩溃),因为测试可执行文件链接到了动态库,而这并不是我想要的。
具体来说,HLib
和SimpleLib
的测试都应该通过,并且我应该能够在cabal repl
和hlib
目录中都运行simplelib
。
我尝试过的其他操作:this answer,this answer(我无法编译),this和读取the docs(导致“重定位”错误)。
目前,我正在使用GHC-7.10.3,但是如果在8.0中明显更方便,那很好。
[1]从lol/challenges简化。
[2]下载并运行./sandbox-init
。这将构建HLib
(隐式构建CLib
和SimpleLib
,后者是依赖于HLib
的Haskell库)。
最佳答案
一旦您知道一些技巧,在Haskell库中包含C或C++库就很简单了。
我从article中获得了核心,尽管看起来似乎太复杂了。您可以使用具有Simple
构建类型(即没有特殊的Setup.hs
),没有makefile以及没有外部工具(例如c2hs
)的cabal(当前为1.25)。
要包含来自纯C库的符号:
Include-dirs: relative/path/to/headers/
或Includes: relative/path/to/myheader.h
。 C-sources: relative/path/to/csources/c1.c, relative/path/to/csources/c2.c, etc
。 C++还有一些额外的功能:
.cpp
文件添加到cabal文件中的C-sources
字段中。 .cpp
文件中的所有函数上,添加extern "C"
以避免名称修改。 #ifdef __cplusplus ... #endif
包围(请参阅n.m.的答案)。 extra-libraries: stdc++
添加到cabal文件中,并使用g++
与ghc-options: -pgmlg++
链接。 .c(pp)
)起作用,则可能必须弄乱在cabal文件中列出cabal repl
文件的顺序。有关更多信息,请参见this ticket。 就是这样!您可以看到一个完整的工作示例here,它可以同时使用
stack
和cabal
。关于haskell - 将C++库与Haskell库静态链接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37572628/