Hi Wolfgang, On Oct 12, 2007, at 15:22, Wolfgang Jeltsch wrote:
Hello,
what are good approaches for creating Haskell bindings to C++ libraries? The most promising so far seems to create C wrappers around the C++ libraries and then bind to them. Is it feasible to bind directly to C++ using ccall by relying on some standardized C++ ABI? What about H/Direct? Are there any other good ways?
Since the name mangling of C++ members, classes and functions are compiler specific, I don't think there is a good way of directly calling the C++ functions and methods. I wrapped all C++ methods of my classes in C functions. I use the following structure: C++ header file tvpi.hh: #ifndef __TVPI_H #define __TVPI_H namespace Tvpi { class Domain { public: Domain(); void joinWiden(Domain& prev, mpz_class extrapolate); }; #endif // __TVPI_H ========================== C header file tvpi_c.h #ifndef TVPI_C_H_ #define TVPI_C_H_ #ifdef __cplusplus extern "C" { #endif // __cplusplus #undef TVPI_TYPE_DECLARATION #define TVPI_TYPE_DECLARATION(Type) \ typedef struct Type ## _tag Type ## _t; \ typedef Type ## _t * Type ## _p; \ typedef Type ## _t const* const_ ## Type ## _p TVPI_TYPE_DECLARATION(Domain); Domain_p tvpiNew(void); void tvpiFree(Domain_p d); void tvpiJoin(Domain_p d1, Domain_p d2); #ifdef __cplusplus } #endif // __cplusplus #endif // TVPI_C_H_ ========================== C wrapper file, tvpi_c.cpp: #include "tvpi_c.h" #include "tvpi.hh" using namespace Tvpi; template<class ToType, class FromType> const ToType* to_const(const FromType* x) { return reinterpret_cast<const ToType*>(x); } template<class ToType, class FromType> ToType* to_nonconst(FromType* x) { return reinterpret_cast<ToType*>(x); } Domain_p tvpiNew() { return to_nonconst<Domain_t, Domain>(new Domain()); } void tvpiFree(Domain_p d) { delete to_nonconst<Domain, Domain_t>(d); } Domain_p tvpiCopy(Domain_p d) { return to_nonconst<Domain_t, Domain> (new Domain(*to_const<Domain, Domain_t>(d))); } void tvpiJoin(Domain_p d1, Domain_p d2) { mpz_class w(-1); to_nonconst<Domain, Domain_t>(d2)->joinWiden(*to_nonconst<Domain, Domain_t>(d1 ), w); } ========================== I'm not claiming it's pretty, but it works on several g++ versions. You also need to pass something like -pgml g++ -optl -pg to ghc so it know that it should link using g++ (and thereby linking against the C++ runtime). Hope this helps, Axel.