如何在Haskell项目中使用DLL?
我想在Haskell项目中使用外部库RDFox 。
上下文:我正在使用GHC 7.10和堆栈 ,都是64位的Windows和Linux。 RDFox是用C ++编程的。 RDFox共享库(.dll,.so)可以用Java和Python包装下载。
目标:我想在我的Haskell项目中重用RDFox(.dll,.so)编译的库,所以我需要为RDFox创build一个Haskell包装器。
问题:对于Haskell来说相对较新,我很难知道从哪里开始。 我find了关于这个主题的几个页面(来自Haskell wiki和StackOverflow),但是工作stream和configuration对我来说并不清楚。
问题:我想知道:
- 如何configuration堆栈和cabal使用外部库,build立在Windows 或 Linux(不同的机器,相同的存储库)。
- 如何在此外部库上configurationGHCi进行交互式testing。
- Python包装器翻译成Haskell是最好的方法吗? 我想避免对RDFox C ++代码的分析。
-
您需要在
.cabal
文件的executable
部分中使用extra-lib-dirs
和extra-libraries
,如下所示: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
),你会遇到链接顺序问题。看到这个例子。 不要被这个名字所迷惑,因为它可以和
.so
文件一起工作。 -
stack ghci
应该只是工作,只要它能find你的库(Linux上的LD_LIBRARY_PATH
)。 -
C API(在您的问题的评论中提到)已经在那里。 您只需要编写Haskell FFI签名,例如:
foreign import ccall safe "helloWorld" c_helloWorld :: IO ()
我非常强烈地build议使用
safe
ccalls,并且不要将函数包装在unsafePerformIO
。如果你需要传递非不透明的结构,你可能想要调查
c2hs
或hsc2hs
,但我认为你不需要。 看到这个问题的更多细节。
您需要为C ++ api和Haskell包装器创build一个C导出的包装器,将其包装为FFI到C导出的包装器。
在这里描述的C#和Haskell之间的封送: 从C#调用Haskell
但它与C ++和Haskell之间的编组非常相似
例如,创buildC ++导出函数:
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数据types(类和结构),您需要在Haskell中创buildC ++数据types模拟。 然后,您需要描述从C ++到Haskell以及从Haskell到C ++的编组数据types。
在Haskell中,这意味着您需要为您的数据types创buildStorable实例。
从这个文档回答:
ghc -c Adder.hs ghc -c StartEnd.c ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o