I have a call to a Fortran function, the first argument of which is a function, for which I would like to use a C++ member-function of the form,
void Obj::memberF(double* x,double* res)
with Obj
having the copy-constructor disabled (and this becomes important as shown below).
The Fortran subroutine is of the form
subroutine solve(f,len,x)
with f
taking two arguments, x
and rhs
, both of which are real arrays. len
stands for the length of these arrays.
(Essentially, need to call the residue function in a non-linear solver library)
For this purpose, irrespective of the eventual C++ approach, we will need a binder and is as follows
binder.f90
SUBROUTINE cpp_solve(cpp_f,len,x) BIND(C, NAME='cpp_solve')
USE, INTRINSIC :: iso_c_binding, ONLY : c_int, c_float
INTERFACE
SUBROUTINE cpp_f(x,rhs) BIND(C)
USE, INTRINSIC :: iso_c_binding, ONLY : c_float
REAL(c_float) :: x(:)
REAL(c_float) :: rhs(:)
END SUBROUTINE cpp_f
END INTERFACE
INTEGER(c_int) :: len
REAL(c_float) :: x(len)
CALL solve(cpp_f,len,x)
END SUBROUTINE cpp_solve
For the C++ program, first, a wrapper is needed for these functions
wrap.h
extern "C" {
void cpp_f(double*,double*);
void cpp_solve(void (Obj::*cpp_f)(double*,double*),int*,double*);
}
The main program is as follows
main.cpp
#include "wrap.h"
int main {
int len = 2;
std::vector<double> x(len);
// Multiple lines to initialize foo
// Creating a global Obj is not feasible
// ...
Obj current_object(foo);
// WHAT GOES HERE?
// cpp_solve(...,len,x);
}
Below are a few approaches I've considered, starting with recent C++ features,
1) Note that the copy-constructor of Obj
has been disabled for other reasons and is the constraint. This prevents me from using std::bind
to attach the current instance and obtain a function pointer.
2) Also, defining another function extra_function(Obj& obj, double*,...)
and then using a lambda to just return obj.memberF
is not an option either, as that would require me to specify a capture, given the custom object and I need a function pointer only.
3) A simpler option would be to just obtain the member function pointer and then, pass the current instance as follows
typedef void (Obj::*fptr)(double*,double*);
fptr current_fPointer = &Obj::memberF;
cpp_solve(current_object.*current_fPointer,len,x);
This gives me the 'invalid use of non-static member function' error.
Is there an alternative approach I could use to obtain the function pointer?
TBH, I'm actually trying to call a Fortran 77 routine using these C++11 features, so that's some retrofuturism.