我想在Haskell项目中使用外部库RDFox。
上下文:我正在使用GHC 7.10和stack在64位上运行Windows和Linux。 RDFox是用C ++编程的。可以使用Java和Python包装器下载RDFox共享库(.dll,.so)。
目标:我想在我的Haskell项目中重用RDFox(.dll,.so)中的编译库,所以我需要为RDFox创建一个Haskell包装器。
问题:对于Haskell来说相对较新,我很难知道从哪里开始。我找到了几个关于这个主题的页面(来自Haskell wiki和StackOverflow),但工作流程和配置对我来说并不清楚。
问题:我想知道:
- 如何配置堆栈和cabal以使用外部库,在Windows 或 Linux(不同的机器,相同的存储库)上构建。
- 如何在此外部库上配置GHCi以进行交互式测试。
- 将Python包装器转换为Haskell是最好的方法吗?我想避免分析RDFox C ++代码。
醇>
答案 0 :(得分:1)
您需要在extra-lib-dirs
文件的extra-libraries
部分中使用executable
和.cabal
,如下所示:
name: MyApp
version: 0.1.0.0
synopsis:
homepage:
author: simon.bourne
category:
build-type: Simple
cabal-version: >=1.10
library
exposed-modules: HelloWorld
build-depends: base >= 4.7 && < 5
hs-source-dirs: src
default-language: Haskell2010
executable MyApp
main-is: Main.hs
extra-lib-dirs: lib
extra-libraries: helloWorld
build-depends: base >= 4.7 && < 5,
MyApp
hs-source-dirs: app
default-language: Haskell2010
将你的dll和.so放在lib
中。请注意,如果在linux上使用静态库(.a
而不是.so
),则会遇到链接顺序问题。
有关示例,请参阅this。不要被名称所迷惑,因为它适用于.so
个文件。
stack ghci
应该可以正常工作,前提是它可以找到您的库(在Linux上LD_LIBRARY_PATH
)。
C API(在您的问题的评论中提到)已经存在。您只需要编写Haskell FFI签名,例如:
foreign import ccall safe "helloWorld" c_helloWorld :: IO ()
我非常强烈建议使用safe
ccalls,并且不要将函数包装在unsafePerformIO
中。
如果您需要传递不透明的结构,可能需要调查c2hs
或hsc2hs
,但我认为您不需要。有关详细信息,请参阅此question。
答案 1 :(得分:1)
您需要为C ++ api和Haskell包装器创建一个C导出的包装器到FFI到C导出的包装器。
C#和Haskell之间的编组说明如下: Calling Haskell from C#
但它在C ++和Haskell之间的编组非常相似
例如,创建C ++导出函数:
extern "C" __declspec(dllexport) int __cdecl addFive(int number);
extern "C" __declspec(dllexport) int __cdecl addFive(int number)
{
return number + 5;
}
在Haskell中,您需要导入代码:
foreign import ccall "addFive" addFive :: Int -> Int
然后你可以在Haskell中使用addFive作为典型的Haskell函数
对于compbound数据类型(类和结构),您需要在Haskell中创建C ++数据类型模拟。然后,您需要描述如何从C ++到Haskell以及从Haskell到C ++编组数据类型。
在Haskell中,这意味着您需要为数据类型创建可存储实例。
答案 2 :(得分:0)
来自this documentation的答案:
ghc -c Adder.hs
ghc -c StartEnd.c
ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o