繁体   English   中英

将没有复制构造函数的类的指向成员函数的指针传递到 Fortran

[英]Pass pointer-to-member-function for class without copy constructor into Fortran

我有一个 Fortran 函数的调用,它的第一个参数是一个函数,我想使用形式的 C++ 成员函数,

void Obj::memberF(double* x,double* res)

Obj禁用了复制构造函数(这变得很重要,如下所示)。

Fortran 子程序的形式为

subroutine solve(f,len,x)

f接受两个参数xrhs ,它们都是实数数组。 len代表这些数组的长度。

(本质上,需要在非线性求解器库中调用残差函数)

为此,无论最终的 C++ 方法如何,我们都需要一个活页夹,如下所示

活页夹.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

对于C++程序,首先这些函数需要一个包装器

包裹.h

extern "C" {
  void cpp_f(double*,double*);
  void cpp_solve(void (Obj::*cpp_f)(double*,double*),int*,double*);
}

主要程序如下

主程序

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

下面是我考虑过的一些方法,从最近的 C++ 特性开始,

1)注意Obj的copy-constructor由于其他原因被禁用,是约束。 这阻止我使用std::bind附加当前实例并获取函数指针。

2)另外,定义另一个函数extra_function(Obj& obj, double*,...)然后使用 lambda 来只返回obj.memberF是一个选项,因为这需要我指定一个捕获,给定自定义对象我只需要一个函数指针。

3)更简单的选择是只获取成员函数指针,然后按如下方式传递当前实例

typedef void (Obj::*fptr)(double*,double*);

fptr current_fPointer = &Obj::memberF;
cpp_solve(current_object.*current_fPointer,len,x);

这给了我“非静态成员函数的无效使用”错误。

有没有我可以用来获取函数指针的替代方法?

TBH,我实际上是在尝试使用这些 C++11 功能调用 Fortran 77 例程,所以这是一些逆向未来主义。

如果这是一个单线程程序,实用的方法可以使用带有额外函数的全局指针变量

static Obj *g_obj;

static void extra_func(double *x1, double *x2)
{
    g_obj->memberF(x1, x2);
}

void call_f77(Obj *o1, int *len, double *x)
{
    g_obj = o1;
    cpp_solve(extra_func, len, x);
}

另一种方法,如果您可以修改 Fortran 代码(并且 Fortran 可以以某种方式透明地传递对象指针),您可以通过 Fortran 将相关对象隧道传输到extra_func ,例如

static void extra_func(void *p, double *x1, double *x2)
{
    Obj *obj = static_cast<Obj*>(p);
    obj->memberF(x1, x2);
}

void call_f77(Obj *o1, int *len, double *x)
{
    cpp_solve(extra_func, o1, len, x);
}

在 Fortran 中(请原谅,我从未见过任何 Fortran 代码):

SUBROUTINE solve(cpp_f, obj, len, x)
...
CALL cpp_f(obj, x, rhs)
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM