Function pointer arrays in Fortran
The declaration "real, external :: f" doesn't really make "f" into a full pointer since you can't change the procedure that it points -- it does permit you to pass this single function to another routine., So you also need the "pointer" attribute. There are examples on page 267 of "Fortran 95/2003 explained" by Metcalf, Reid & Cohen -- a google search for "fortran procedure pointer" will bring up this page. A simple example close to yours is "real, external, pointer :: f_ptr". Alternatively: "procedure (f), pointer :: f_ptr". This is a Fortran 2003 feature -- http://gcc.gnu.org/wiki/Fortran2003 and http://gcc.gnu.org/wiki/ProcedurePointers lists partial support in gfortran, best with 4.5. I'm not sure whether "dimension" is directly allowed, but you can assign a procedure to a pointer, which provides a lot of flexibility. You can also put the pointer into a derived type, which could be made into an array.
Edit: here is a code example which works with gfortran 4.5: Edit 2: line commented out per comments below.
module ExampleFuncs
implicit none
contains
function f1 (x)
real :: f1
real, intent (in) :: x
f1 = 2.0 * x
return
end function f1
function f2 (x)
real :: f2
real, intent (in) :: x
f2 = 3.0 * x**2
return
end function f2
function fancy (func, x)
real :: fancy
real, intent (in) :: x
interface AFunc
function func (y)
real :: func
real, intent (in) ::y
end function func
end interface AFunc
fancy = func (x) + 3.3 * x
end function fancy
end module ExampleFuncs
program test_proc_ptr
use ExampleFuncs
implicit none
! REMOVE: pointer :: func
interface
function func (z)
real :: func
real, intent (in) :: z
end function func
end interface
procedure (func), pointer :: f_ptr => null ()
type Contains_f_ptr
procedure (func), pointer, nopass :: my_f_ptr
end type Contains_f_ptr
type (Contains_f_ptr), dimension (2) :: NewType
f_ptr => f1
write (*, *) f_ptr (2.0)
write (*, *) fancy (f_ptr, 2.0)
f_ptr => f2
write (*, *) f_ptr (2.0)
write (*, *) fancy (f_ptr, 2.0)
NewType(1) % my_f_ptr => f1
NewType(2) % my_f_ptr => f2
write (*, *) NewType(1) % my_f_ptr (3.0), NewType(2) % my_f_ptr (3.0)
stop
end program test_proc_ptr
Related videos on Youtube
Eduardo Dobay
Updated on March 14, 2020Comments
-
Eduardo Dobay over 3 years
I can create function pointers in Fortran 90, with code like
real, external :: f
and then use
f
as an argument to another function/subroutine. But what if I want an array of function pointers? In C I would just dodouble (*f[])(int);
to create an array of functions returning double and taking an integer argument. I tried the most obvious,
real, external, dimension(3) :: f
but gfortran doesn't let me mix EXTERNAL and DIMENSION. Is there any way to do what I want? (The context for this is a program for solving a system of differential equations, so I could input the equations without having a million parameters in my subroutines.)
-
AlanSE almost 12 yearsYour code runs correctly with gfortran but does not compile with either g95 or the Intel Fortran compiler. I've saved the error messages and would be happy to post them, where would be an appropriate place to do so?
-
AlanSE almost 12 yearsBoth compiler messages are similar, and both are at line 51 (after the implicit none) at variable "func". ifort says "error #6409: This name has already been used as an external procedure name" and g95 says "Symbol 'func' at (1) conflicts with the same name in an encompassing program unit". I hope that sufficiently identifies the error. Again, gfortran is not bothered by this.
-
AlanSE almost 12 yearsYeah, I think that "pointer :: func" line just shouldn't be there. I'm not sure what that was supposed to accomplish, there's no reason to suspect there would be a problem without it.