2015-07-03 56 views
42

我想在Haskell项目中使用外部库RDFox如何在Haskell项目中使用DLL?

上下文:我正在使用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. 如何堆叠和小集团配置为使用外部库,建立在Windows Linux操作系统(不同的机器,不同的版本库)。
  2. 如何在此外部库上配置GHCi以进行交互式测试。
  3. 翻译Python包装到Haskell是最好的方法吗?我想避免分析RDFox C++代码。
+1

首先您可能需要为C++ api创建一个C导出包装。 – alternative

+0

是不是可以直接在Haskell中创建包装?我的意思是,如果我必须创建一个C封装器,然后创建一个Haskell封装器,那有什么意义? –

+1

C++中的命名约定比C中的命名约定复杂得多。我不认为FFI支持非外部C事件的名称修改。 – alternative

回答

0

this documentation答:

ghc -c Adder.hs 
ghc -c StartEnd.c 
ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o 
1
  1. 你需要使用extra-lib-dirsextra-libraries.cabal文件的executable段像这样:

    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

您需要为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中,它意味着您需要为您的数据类型创建Storable实例。