Aleksandar Donev wrote:
> By using some minimal C code I have written Fortran 90 codes to
> emulate procedure pointers, without the use of VALUE.
Here is an example from one of the test codes. Most of this is generated
automatically using macros so that it can relatively easily be repeated
for different procedures. It relies on the POINTER attribute in order
to do the trick of passing the address of a procedure through an
integer argument.
Aleks
TYPE :: Procedure_Pointer
INTEGER (KIND=C_ADDRESS) :: c_pointer = C_NULL_FUNPTR
INTEGER (KIND=C_ADDRESS), POINTER :: f_pointer => NULL ()
END TYPE
TYPE (Procedure_Pointer) :: ATestSubroutine
INTERFACE
SUBROUTINE Call_TestSubroutine (proc_ptr, n)
! Lie about the interface of external procedure
USE ISO_C_BINDING_Extended
INTEGER (KIND=C_INT), INTENT (IN) :: n
INTEGER (KIND=C_ADDRESS), INTENT (IN), TARGET :: proc_ptr
! This is the trick---it will pass the address in |f_pointer|
END SUBROUTINE
END INTERFACE
ATestSubroutine%c_pointer = C_LOC_Subroutine (x=MyTestSubroutine)
CALL C_F_POINTER (CPTR=ATestSubroutine%c_pointer, &
FPTR=ATestSubroutine%f_pointer)
CALL Call_TestSubroutine (ATestSubroutine%f_pointer, 13)
! Call the wrapper that will call the actual procedure
CONTAINS
SUBROUTINE MyTestSubroutine (n)
INTEGER (KIND=C_INT), INTENT (IN), VALUE :: n
WRITE (*,*) "Fortran subroutine called with n=", n
END SUBROUTINE MyTestSubroutine
This must be an external proc since we are lying about its interface:
SUBROUTINE Call_TestSubroutine (proc_ptr, n)
USE ISO_C_BINDING_Extended
INTEGER (KIND=C_INT), INTENT (IN) :: n
INTERFACE
SUBROUTINE proc_ptr (n)
USE ISO_C_BINDING_Extended
INTEGER (KIND=C_INT), INTENT (IN) :: n
END SUBROUTINE
END INTERFACE
CALL proc_ptr (n)
END SUBROUTINE
|