Setup: I have a Haskell library HLib
which makes calls to a C/C++ backend CLib
for efficiency. The backend is small and specialized for use with
Including a C or C++ library with a Haskell library is trivial once you know a few tricks.
I got the core from this article, though it seems to overcomplicate things. You can use cabal (currently 1.25) with a Simple
build type (i.e. no special Setup.hs
), no makefile, and no external tools like c2hs
.
To include symbols from a pure C library:
Include-dirs: relative/path/to/headers/
or Includes: relative/path/to/myheader.h
. C-sources: relative/path/to/csources/c1.c, relative/path/to/csources/c2.c, etc
.There's a couple of extra bits for C++:
.cpp
files to the C-sources
field in the cabal file. .cpp
files that Haskell needs access to, add extern "C"
to avoid name mangling.#ifdef __cplusplus ... #endif
(see n.m.'s answer).extra-libraries: stdc++
to your cabal file, and link with g++
using ghc-options: -pgmlg++
..c(pp)
files in the cabal file if you want dynamic linking (i.e. cabal repl
) to work. See this ticket for more information.That's it! You can see a complete working example here which works with both stack
and cabal
.
GHC cannot really understand C++ header files. It needs pure C code. The common way for a C++ header file to provide C interface is to isolate away C++ parts with #ifdef __cplusplus
, e.g.:
#ifdef __cplusplus
extern "C" { // C compilers and various C-based FFIs don't like this
#endif
void foo();
#ifdef __cplusplus
}
#endif
In addition, GHCi is historically known to have problems with linking C++ code. For example, at one point it didn't understand weak symbols (often produced by the compiler in conjunction with inline functions and template instantiations). You might be seeing one of these problems. I'd recommend filing a bug report to the GHC team.