静态链接C++库和Haskell库

cro*_*eea 12 haskell ghc cabal

设置:我有一个Haskell库HLib,可以调用C/C++后端CLib来提高效率.后端很小,专门用于HLib.的接口CLib被通过暴露HLib; HLib测试,HLib基准测试和第三方库依赖于HLib不会直接进行FFI调用CLib.从测试/基准/第三方lib的角度来看,HLib应该是纯粹的Haskell.这意味着在,例如小集团文件部分,HLib测试,应该有任何引用-lCLib,libCLib等等,只有build-dependsHLib,并且可执行文件不应该需要寻找一个动态CLib库.我需要能够构建和运行HLib第三方库中的所有可执行文件,以及运行cabal repl开发.

最初,CLib写于纯C.卡瓦尔具有用于这种情况下的支持,并且我可以集成CLibHLib在精确地,通过使用上面描述的方式include-dirs,c-sourcesincludes在小集团文件字段.

CLib已经发展成为一个C++库,我无法弄清楚如何让cabal轻松集成.相反,我使用自定义构建和Setup.hs的makefile,就像这样.你可以在这里看到这个方法的一个小例子1,2.

在那个例子中,我无法运行cabal repl,HLib因为"加载档案不受支持".这实际上意味着我需要一个动态C++库,它很容易创建(在CLibmakefile中有一个注释行来完成它).但是,如果我确实创建了动态C++库,那么HLib由于"没有这样的文件或目录libclib.so" ,测试会在运行时失败.这很糟糕(除了崩溃),因为测试可执行文件链接到动态库,这不是我想要的.

具体来说,测试HLibSimpleLib应该通过,我应该能够cabal replhlibsimplelib目录中运行.

我尝试过的其他事情:这个答案,这个答案(我无法编译),这个,以及阅读文档(导致"重定位"错误).

我目前正在使用GHC-7.10.3,但如果在8.0中这样做要容易得多,那很好.

[1] lol/challenge简化.

[2] 下载并运行./sandbox-init.这构建HLib(隐式构建CLib,并且SimpleLib,它是依赖于的Haskell库HLib.

cro*_*eea 5

一旦你了解了一些技巧,将C或C++库与Haskell库包含在一起是微不足道的.

我从这篇文章中获得了核心,虽然它似乎使事情过于复杂.你可以使用cabal(目前1.25)与Simple构建类型(即没有特殊Setup.hs),没有makefile,也没有外部工具c2hs.

要包含纯C库中的符号:

  1. 在您的cabal文件中,添加Include-dirs: relative/path/to/headers/Includes: relative/path/to/myheader.h.
  2. 添加C-sources: relative/path/to/csources/c1.c, relative/path/to/csources/c2.c, etc.

C++有几个额外的位:

  1. 您可以将.cpp文件添加到C-sourcescabal文件中的字段.
  2. .cppHaskell需要访问的文件中的所有函数上,添加extern "C"以避免名称损坏.
  3. 用头文件中的所有非纯C代码包围#ifdef __cplusplus ... #endif(参见nm的答案).
  4. 如果使用标准C++库,则需要添加extra-libraries: stdc++到cabal文件中,并g++使用ghc-options: -pgmlg++.
  5. 如果您希望动态链接(即)工作,您可能需要对列出cabal文件中的文件的顺序进行一些调整.有关更多信息,请参阅此票证..c(pp)cabal repl

而已!你可以在这里看到一个完整的工作示例,它适用于stackcabal.