[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