[Haskell] C++ bindings

Axel Simon A.Simon at kent.ac.uk
Fri Oct 12 10:46:51 EDT 2007


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.



More information about the Haskell mailing list