I would like to use an external library, RDFox, in a Haskell project.
Context: I am working on Windows and Linux, both 64 bits, using GHC 7.10 and stack. RDFox is programmed in C++. RDFox shared libraries (.dll, .so) can be downloaded with Java and Python wrappers.
Aim: I would like to reuse the compiled libraries from RDFox (.dll, .so) in my project in Haskell, so I need to create a Haskell wrapper for RDFox.
Issues: Being relatively new to Haskell, I have difficulty to know where to start. I found several pages about the subject (from the Haskell wiki and StackOverflow), but the workflow and configuration are not clear to me.
Questions: I would like to know:
- How to configure stack and cabal to use external library, to build on Windows or Linux (different machines, same repository).
- How to configure GHCi for interactive testing on this external library.
- Is the translation of the Python wrapper to Haskell the best way to go? I would like to avoid the analysis of the RDFox C++ code.
You'll need to use extra-lib-dirs and extra-libraries in the executable section of your .cabal file like so:
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
Put your dll and .so in lib. Be warned, you'll run into link order problems if you use a static library (.a instead of .so) on linux.
See this for an example. Don't be fooled by the name as it works fine with .so files.
stack ghci should just work provided it can find your library (LD_LIBRARY_PATH on linux).
The C API (mentioned in the comments on your question) is already there. You just need to write the Haskell FFI signatures, for example:
foreign import ccall safe "helloWorld" c_helloWorld :: IO ()
I'd very strongly advise using safe ccalls, and don't wrap the functions in unsafePerformIO.
If you need to pass non opaque structs, you might want to investigate c2hs or hsc2hs, but I don't think you'll need to. See this question for more details.
You need to create a C-exported wrapper for the C++ api and Haskell wrapper to FFI to C-exported wrapper.
Marshaling between C# and Haskell described here: Calling Haskell from C#
but it very similar marshaling between C++ and Haskell
For example, create C++ export function:
extern "C" __declspec(dllexport) int __cdecl addFive(int number);
extern "C" __declspec(dllexport) int __cdecl addFive(int number)
{
return number + 5;
}
In Haskell you need import code:
foreign import ccall "addFive" addFive :: Int -> Int
Then you can use addFive in Haskell as typical Haskell-function
For compbound data types (classes and structures) you need create C++ data-type analog in Haskell. Then you need describe how marshal data types from C++ to Haskell and from Haskell to C++.
In Haskell it means that you need create Storable instance for you data types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With