This is the mail archive of the gsl-discuss@sources.redhat.com mailing list for the GSL project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);
}




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]