I want to use an slatec subroutine (fortran) in C++. Usually these subroutines take subroutines/functions as arguments.
I have a class that performs some calculations and I would like to call a subroutine with a functor as an argument. Why? because the functor could access information from the main class.
These slatec subroutines do not allow to take an state or void* parameter.
A minimal example would be:
// compile with
// g++ dgaus.cpp -lstdc++ -lgfortran -lslatec -Wall -g
#include <iostream>
extern "C"
{
// a not complicated subroutine in slatec
void dgaus8_(void(f)(double* x), double* a, double* b, double* err, double* ans,
int* ierr);
};
// example function
inline void f(double* x) {
*x = 3.0*(*x)*(*x);
}
// what i want/need is to use the following instead of the simple function above,
// I will have states and internals that change.
struct functor{
functor() { }
functor(double c_): c(c_) { }
void operator()(double* x){
*x = c*(*x)*(*x);
}
double c;//<! this will be a complicated object that changes
};
int main(int argc, char **argv) {
{
double ans=0.0;
double a=1.0;
double b=3.0;
double err=0.0001;
int ierr=0;
// works
dgaus8_(f, &a, &b, &err, &ans, &ierr);
std::cout << "\n@> Answer : " << ans;
std::cout << "\n@> Error : " << err;
std::cout << "\n@> Flag : " << ierr;
std::cout << "\n";
}
{
double ans=0.0;
double a=1.0;
double b=3.0;
double err=0.0001;
int ierr=0;
double c = 3.0;
// in the full code c is an object that calls
// dgaus8_, and functor is a member of it.
// f = new functor(this);
functor *f2 = new functor(c);
// doesn't work
dgaus8_(*f2, &a, &b, &err, &ans, &ierr);
std::cout << "\n@> Answer : " << ans;
std::cout << "\n@> Error : " << err;
std::cout << "\n@> Flag : " << ierr;
std::cout << "\n";
delete(f2);
}
return 0;
}
I got the error:
gaus.cpp: In function ‘int main(int, char**)’:
dgaus.cpp:64:43: error: cannot convert ‘functor’ to ‘void (*)(double*)’ for argument ‘1’ to ‘void dgaus8_(void (*)(double*), double*, double*, double*, double*, int*)’
dgaus8_(*f2, &a, &b, &err, &ans, &ierr);
Is it possible to use a functor instead of a regular function when calling extern fortran functions?
My actual "design", solver calls slatec subroutine functor as parameter,
class sys
void solver(...)
func functor(..)
functor
functor(s)
sys s
operator()
functor access and call methods from s
or solver calls slatec subroutine function as parameter,
class
void solver
void function
what should be a correct design if you want to pass a function to fortran suboroutine, but this function is a result of a construction with many parameters an undetermined states within the calling class?