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.

_______________________________________________
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell

Reply via email to