如何在Haskell项目中使用DLL?

时间:2015-07-03 07:34:49

标签: haskell shared-libraries ghc cabal haskell-stack

我想在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),但工作流程和配置对我来说并不清楚。

问题:我想知道:

  
      
  1. 如何配置堆栈和cabal以使用外部库,在Windows Linux(不同的机器,相同的存储库)上构建。
  2.   
  3. 如何在此外部库上配置GHCi以进行交互式测试。
  4.   
  5. 将Python包装器转换为Haskell是最好的方法吗?我想避免分析RDFox C ++代码。
  6.   

3 个答案:

答案 0 :(得分:1)

  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个文件。

  2. stack ghci应该可以正常工作,前提是它可以找到您的库(在Linux上LD_LIBRARY_PATH)。

  3. C API(在您的问题的评论中提到)已经存在。您只需要编写Haskell FFI签名,例如:

    foreign import ccall safe "helloWorld" c_helloWorld :: IO ()
    

    我非常强烈建议使用safe ccalls,并且不要将函数包装在unsafePerformIO中。

    如果您需要传递不透明的结构,可能需要调查c2hshsc2hs,但我认为您不需要。有关详细信息,请参阅此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