设置:我有一个Haskell库HLib,它可以调用C/C++后端CLib以提高效率。后端很小,专用于HLibCLib的接口(interface)只能通过HLib公开; HLib测试,HLib基准测试和依赖HLib的第三方库不会直接对CLib进行FFI调用。从test/benchmark/3rd party lib的角度来看,HLib应该纯粹是Haskell出现。这意味着在例如HLib测试的cabal文件部分中,不应引用-lCLiblibCLib等,仅应在build-depends上引用HLib,并且可执行文件无需寻找动态CLib库。我需要能够在HLib和第三方库中构建和运行所有可执行文件,以及运行cabal repl进行开发。

最初,CLib是用纯C语言编写的。Cabal支持这种情况,并且我可以使用cabal文件中的CLibHLibinclude-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的测试在运行时失败了。这很糟糕(除了崩溃),因为测试可执行文件链接到了动态库,而这并不是我想要的。

具体来说,HLibSimpleLib的测试都应该通过,并且我应该能够在cabal replhlib目录中都运行simplelib

我尝试过的其他操作:this answerthis answer(我无法编译),this和读取the docs(导致“重定位”错误)。

目前,我正在使用GHC-7.10.3,但是如果在8.0中明显更方便,那很好。

[1]从lol/challenges简化。

[2]下载并运行./sandbox-init。这将构建HLib(隐式构建CLibSimpleLib,后者是依赖于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字段中。
  • 在Haskell需要访问的.cpp文件中的所有函数上,添加extern "C"以避免名称修改。
  • 将头文件中的所有非纯C代码都用#ifdef __cplusplus ... #endif包围(请参阅n.m.的答案)。
  • 如果您使用标准C++库,则需要将extra-libraries: stdc++添加到cabal文件中,并使用g++ghc-options: -pgmlg++链接。
  • 如果要使动态链接(即.c(pp))起作用,则可能必须弄乱在cabal文件中列出cabal repl文件的顺序。有关更多信息,请参见this ticket

  • 就是这样!您可以看到一个完整的工作示例here,它可以同时使用stackcabal

    关于haskell - 将C++库与Haskell库静态链接,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37572628/

    10-10 10:09