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