Fortran:将成员过程传递给外部函数

时间:2015-07-27 04:04:53

标签: fortran

如何指向类型绑定过程?假设我有一些外部子程序,它将一个指向一个只接受一个参数的函数的指针作为参数。

call integrator(f0)

如果在某处定义函数f0使其看起来像

,这将起作用
function f0(x) result(val)
 ... do something...
end function

但是现在我有一个带有一些类型绑定过程的SomeClass类型。其中一个类型绑定程序是

 function integrand(this,x) result(val)
  class(SomeClass), intent(in) :: this  
  ...do something...
 end function

我有一个相同类型的另一个类型绑定过程想要调用上面的子例程将第一个类型绑定过程传递给它,但我不知道如何编写它!让我先尝试一下,有点天真,

function CalculateIntegral(this) result(val)
 class(SomeClass), intent(in) :: this

 call integrator(this%integrand)
end function

这给了我

 call integrator(this%integrand)
                               1
Error: Expected argument list at (1)
我从this discussion学到的是因为这个%integrand没有返回指向函数的指针,而是绑定到函数。

所以,现在我来试试这个

function CalculateIntegral(this) result(val)
 class(SomeClass), intent(in) :: this

 call integrator(integrand)
end function

并且它编译但是给了我一个Memory Reference错误,因为它试图将值(x)传递给类(SomeClass)类的参数(即,这个)。

因此,如果这个%integrand只给我一个绑定而不是一个指向类型绑定成员过程的指针,那么如何在没有第一个" this&#的情况下将我的一个类型绑定成员过程传递给外部子例程34;争论阻碍了吗?

注意:我曾经在python中编码,其中self.integrand可以传递给外部函数,一切都会好的。

编辑:我的坏;我记得错了。如果你试图将self.integrand传递给外部函数,Python会遇到同样的问题。

1 个答案:

答案 0 :(得分:1)

按照@ Vladimir评论中的链接,传递内部程序似乎适用于最近的编译器(注意:我认为第一个例子是下面代码中最简单和最好的):

module mymod
    implicit none

    type mytype
        real :: q
    contains
        procedure :: calc_integral
    end type

contains

function calc_integral( this, a, b ) result( ans )
    class(mytype) :: this
    real :: a, b, ans

    call integrator( myfunc, a, b, ans )
contains
    function myfunc( x ) result( val )
        real :: x, val
        val = this% q * x
    end function
endfunction

end module

!! Some external library.                          
subroutine integrator( func, a, b, ans )
    external :: func
    real :: a, b, ans, func

    ans = func( a ) + func( b )
end

program main
    use mymod
    type(mytype) :: mt

    mt% q = 100.0
    print *, mt% calc_integral( 1.0, 2.0 )  !! gives 300.0
end

在上面的代码中,也可以将模块过程传递给integrator()(而不是传递内部过程),但在这种情况下,this_可能需要myfunc()之类的内容。访问类型组件(参见下一个案例)。

下面是另一种以不同方式传递被积函数的尝试。 这里,指向模块过程myfunc()的指针传递给integrator()

module mymod
    implicit none

    interface
        function integrand_i( x ) result( val )
            real :: x, val
        endfunction
    endinterface

    type mytype
        real :: q
        procedure(integrand_i), nopass, pointer :: integrand
    contains
        procedure :: init
    endtype

    class(mytype), pointer :: this_       
contains

subroutine init( this )
    class(mytype), target :: this
    this% integrand => myfunc
    this_ => this
endsubroutine

function myfunc( x ) result( val )
    real :: x, val
    val = this_ % q * x
endfunction

end module

! subroutine integrator() here

program main
    use mymod
    type(mytype) :: mt
    real :: ans

    call mt% init
    mt% q = 100.0

    call integrator( mt% integrand, 1.0, 2.0, ans )
    print *, ans
end

看起来有点类似于OP在问题中的原始方法(在我看来)。

另一种(不工作)方法是修改上面的init(),以便获得指向内部过程的指针

subroutine init( this )
    class(mytype) :: this

    this% integrand => myfunc
contains
    function myfunc( x ) result( val )
        real :: x, val
        val = this % q * x
    endfunction
endsubroutine

但是这不起作用,因为退出init()时内部过程变得不确定。同样,以下似乎也不起作用(它甚至不用gfortran4.8.2编译)。

type mytype
    ...
contains
    procedure :: integrand
endtype
...
function integrand( this ) result( ptr )
    class(mytype) :: this
    procedure(integrand_i), pointer :: ptr

    ptr => myfunc
contains
    function myfunc( x ) result( val )
        real :: x, val
        val = this % q * x
    endfunction
endfunction

program main
...
call integrator( mt% integrand, 1.0, 2.0, ans )