Is there a way in C++ to effectively create a closure which will be a function pointer? I am using the Gnu Scientific Library and I have to create a gsl_function. This funct
I'm guessing from all those "gsl_" prefixes that the library is not C++, but plain C. Which means it doesn't grok C++ closures (functors). You can't pass a C++ functor to a C function. You'll have to pass void pointers around, cross your fingers and reinterpret_cast them into C oblivion.
Take a look at this simple example of combining boost::bind and boost::function.
Though bradgonesurfing has given a nice answer that will work for converting closures into gsl_function
s without any further thought, I would like to share with you the idiom for doing a direct translation from C++ into C.
Supposing you have the closure:
double a;
[&a](double x){return a+x;}
You would convert translate this into an equivalent function pointer idiom as follows:
struct paramsAPlusX{
double* a;
paramsAPlusX(double & a_):a(&a_){}
}
double funcAPlusX(double x, void* params){
paramsAPlusX* p= (paramsAPlusX*)params;
return *(p->a) + x;
}
//calling code:
double a;
paramsAPlusX params(a);
gsl_function f;
f.function=funcAPlusX;
f.params=¶msAPlusX;
//use f here.
Many C libraries use this sort of idiom, and they don't all use a struct for it (they frequently pass it as two separate parameters to the function) so automatic conversion isn't always possible.
I found below code at.
http://bytes.com/topic/c/answers/657124-interface-problem
// Use in combination with boost::bind.
template<class F>
static double gslFunctionAdapter( double x, void* p)
{
// Here I do recover the "right" pointer, safer to use static_cast
// than reinterpret_cast.
F* function = static_cast<F*>( p );
return (*function)( x );
}
template<class F>
gsl_function convertToGslFunction( const F& f )
{
gsl_function gslFunction;
const void* p = &f;
assert (p != 0);
gslFunction.function = &gslFunctionAdapter<F>;
// Just to eliminate the const.
gslFunction.params = const_cast<void*>( p );
return gslFunction;
}
and use this like
gslFunction gslF = convertToGslFunction( boost::bind( &Sde::drift, &sde, _1 ) );