This is the mail archive of the
gsl-discuss@sources.redhat.com
mailing list for the GSL project.
Re: C++ wrapping
On Mon, Apr 12, 2004 at 01:37:50PM -0600, Gerard Jungman wrote:
>
> The problem is that C++ can never allow you to forget where
> the function pointer came from; even if you give up and try
> to force everything through void *, you still have to remember
> the type so you can make the right cast at the end. It's enough
> to make you cry. When thinking about this, I wondered if you
> could just cast to (double (*func)(double)), forgetting
> about where it came from. It took a little massaging to
> get gcc to compile the attached file; but no amount of
> massaging could get a result other than seg-fault; this is
> not surprising.
Well, you must have done this late at night, you forgot about
the 'this' pointer. Dohh. Below follows a non-segfaulting version.
Note, however, the non-segfaulting version is still a bit
leading, since if 'thing' was a virtual base class,
and it was used in a multiple-inheritance scenario with other
virtual bases classes, then the code below would segfault.
This is because for virtual base classes with virtual
functions, there's a 'thunk' performed to add an offset
during vtable lookup, and the insane recasting will miss this
offset.
--linas
#include <stdio.h>
class thing
{
public:
thing(double y) : _y(y) { }
double foo(double x);
private:
double _y;
};
double thing::foo(double x)
{
return x * _y;
}
int main ()
{
thing t(7.0);
// Too bad the following won't compile.
// void * fp = (void *) &thing::foo;
// double (*recast) (void *, double) = fp;
// cast the hard way....
typedef double (thing::*thing_dd_func_type)(double);
thing_dd_func_type fp = &thing::foo;
void * fprc = reinterpret_cast<void *>(t.*fp);
typedef double (*dd_func_type) (void *, double);
dd_func_type recast = (dd_func_type) (fprc);
// The untyped 'self' is just C++'s 'this'
void * self = (void *) &t;
double answer = recast (self, 6.0);
printf ("the answer to the question is %f\n", answer);
}