How to Avoid Static Member Function When Using Gsl with C++

how to avoid static member function when using gsl with c++

You can easily wrap member functions using the following code (which is a well known solution)

 class gsl_function_pp : public gsl_function
{
public:
gsl_function_pp(std::function<double(double)> const& func) : _func(func){
function=&gsl_function_pp::invoke;
params=this;
}
private:
std::function<double(double)> _func;
static double invoke(double x, void *params) {
return static_cast<gsl_function_pp*>(params)->_func(x);
}
};

Then you can use std::bind to wrap the member function in a std::function. Example:

gsl_function_pp Fp( std::bind(&Class::member_function, &(*this),  std::placeholders::_1) );
gsl_function *F = static_cast<gsl_function*>(&Fp);

However, you should be aware about the performance penalties of std::function before wrapping member functions inside gsl integration routine. See template vs std::function . To avoid this performance hit (which may or may not be critical for you), you should use templates as shown below

template< typename F >
class gsl_function_pp : public gsl_function {
public:
gsl_function_pp(const F& func) : _func(func) {
function = &gsl_function_pp::invoke;
params=this;
}
private:
const F& _func;
static double invoke(double x, void *params) {
return static_cast<gsl_function_pp*>(params)->_func(x);
}
};

In this case, to call a member function you need the following

 Class* ptr2 = this;
auto ptr = [=](double x)->double{return ptr2->foo(x);};
gsl_function_pp<decltype(ptr)> Fp(ptr);
gsl_function *F = static_cast<gsl_function*>(&Fp);

PS: the link template vs std::function explains that compiler usually has an easier time optimizing templates than std::function (which is critical for performance if your code is doing heavy numerical calculation). So even tough the workaround in the second example seems more cumbersome, I would prefer templates than std::function.

C++ class member function to GSL ODE solver

Something like this:

class my_model
{
private: int
ode_gsl_impl(double const t, double const * const y, double * const dydt);

public: static int
ode_gsl(double const t, double const * const y, double * const dydt, void * const opaque)
{
assert(opaque);
return(static_cast<my_model *>(opaque)->ode_gsl_impl(t, y, dydt));
}
};

gsl_odeiv2_system sys
{
&my_model::ode_gsl
, nullptr
, chemosc.NEQ
, reinterpret_cast<void *>(::std::addressof(chemosc))
};

I would like to mention that your original code suffers from name collisions between callback parameter names and class field names.

A function pointer issue. How to efficiently interface with C API (ie. GSL) from C++ class?

Since GSL allows you to pass in arbitrary parameters, you can abuse this to hold the pointer to the instance under question. Then use a static member function to forward to the member function:

class MyClass
{
double foo(double x)
{
...
}
static double foo_wrapper(double x, void *params)
{
return static_cast<MyClass*>(params)->foo(x);
}

double bar(double x)
{
...
gsl_function F;
F.function=&MyClass::foo_wrapper;
F.params=this;

// invoke GSL function passing in F
...
}
};

Can you do better? Is there an easier way? Not really. Any approach you take will be doing this under the covers somewhere.

But you can write a simple wrapper which hides some of this:

class gsl_function_pp : public gsl_function
{
public:
gsl_function_pp(boost::function<double(double)> const& func) : _func(func)
{
function=&gsl_function_pp::invoke;
params=this;
}
private:
boost::function<double(double)> _func;

static double invoke(double x, void *params)
{
return static_cast<gsl_function_pp*>(params)->_func(x);
}
};

This should give you (possibly at a moderate performance penalty due to multiple indirections involved) the type of functionality you'd want:

class MyClass
{
double foo(double x)
{
...
}

double bar(double x)
{
gsl_function_pp F(boost::bind(&MyClass::foo, this, _1));
// invoke GSL function passing in F
...
}
};

The caveat is that you'll have to ensure that any gsl_function_pp object stays in scope for the entire time that the GSL might invoke it. So, don't try to set up a root finder/etc in one function (using a local gsl_function_pp), return, and then perform root finding iterations in another -- you'll get a crash or worse.

Using GSL functions defined in a structure

You don't need to use static function directly. Instead you can write a very general wrapper.

I believe this is a duplicate question. My answer to the question I just linked is based on the wrapper presented here. However, I generalized it using templates to avoid the performance penalty of std::function due to heap allocation of the functor that std::function holds (the original answer only warns the reader about the penalty that is caused by the multiple indirection involved in std::function implementation, and this is negligible in comparison to the problem caused by heap allocation).

EDIT 1: This issue is also discussed here

EDIT 2 (to answer a question you raised in your first comment to my answer). The first caveat is that you have to make sure that whatever std::function holds is not deleted before GSL finish the calculation. Also, @Managu pointed out that the wrapper itself must not be out of scope while GSL works. This is not hard to enforce if you code carefully. Example of bad code:

 // BAD PROGRAM - EXAMPLE OF WHAT YOU MUST NOT DO. DO NOT COPY THIS CODE
// HERE THE WRAPPER GETS PREMATURELY OUT OF SCOPE => CRASH
gsl_function *F
auto ptr = [](double x)->double{return 2*x;};
std::function<double(double)> FF1(std::cref(ptr))

{
gsl_function_pp Fp(FF1);
F = static_cast<gsl_function*>(&Fp);
}
(...)
// CALL GSL

Calling GSL function inside a class in a shared library

It is indeed interesting that people ask this over and over again. One reason may be that the proposed solutions are not easy to understand. I for one had problems understanding and implementing them. (the solutions did not work out of the box for me, as you might expect.)

With the help of tlamadon I just figured out a solution that may be helpful here as well. Let's see what you guys think.

So just to recap, the problem is that you have a class that contains a member function on which you want to operate with something from the GSL library. Our example is useful if the GSL interface requires a

gsl_function F;

see here for a definition.

So here is the example class:

class MyClass {

private:
gsl_f_pars *p; // not necessary to have as member

public:
double obj(double x, void * pars); // objective fun
double GetSolution( void );
void setPars( gsl_f_pars * xp ) { p = xp; };
double getC( void ) ; // helper fun

};

The objective of this exercise is to be able to

  1. initiate MyClass test,
  2. supply it with a paramter struct (or write a corresponding constructor), and
  3. call test.GetSolution() on it, which should return whatever the GSL function was used for (the minimum of obj, a root, the integral or whatever)

The trick is now to put have an element in the parameter struct gsl_f_pars which is a pointer to MyClass. Here's the struct:

struct gsl_f_pars {
double a;
double b;
double c;
MyClass * pt_MyClass;
};

The final piece is to provide a wrapper that will be called inside MyClass::GetSolution() (the wrapper is a stand in for the member function MyClass::obj, which we cannot just point to with &obj inside the class). This wrapper will take the parameter struct, dereference pt_MyClass and evaluate pt_MyClass's member obj:

// Wrapper that points to member function
// Trick: MyClass is an element of the gsl_f_pars struct
// so we can tease the value of the objective function out
// of there.
double gslClassWrapper(double x, void * pp) {
gsl_f_pars *p = (gsl_f_pars *)pp;
return p->pt_MyClass->obj(x,p);
}

The full example is a bit too long to post here, so I put up a gist. It's a header file and a cpp file, it should be working wherever you have GSL. Compile and run with

g++ MyClass.cpp -lgsl -o test
./test

Passing a member function to arbitrary precision C++ quadrature library (Quadpack++)

The function prototype has to have two arguments, and the second one has to be a pointer. I don't know enough about mpf_array to know what it boils down to. If it's not a pointer type, well, that's a problem. (Also a bit of testing shows that having const in front of the params is not going to help.)

Probably more importantly though, it has to be a free function, and can't belong to a class like MyClass (unless it's a static function IIRC). Do you need elements of MyClass inside your function?

(edit based on comment below). The function prototype shown requires a (presumably real) type and a pointer to, basically, all the other arguments, which for you is going to require not only this mpf_array thing but also the MyClass object you need to call it from. So you need to package all those params together into one big ... thing.

struct helper {
mpf_array foo;
MyClass bob;
}

Then we can make a relay function that packages one of these up as the arguments that you need:

mpf relay(mpf t, helper* args) {
return args->bob.actual_function(t, args->foo);
}

Then create a helper struct with your fourier array and your actual object and pass its address as the second param. There should probably be some references in here to avoid copying, but I'm typing straight into this box (so there's probably some other error in here too).

This is ... hackish at best, but it should get the job done with this package anyway. (I have to admit I don't know of any package that would suit better, sorry.)



Related Topics



Leave a reply



Submit