Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29249 Discussions

iso-c-binded functions used as procedure-arguments or called as procedure-pointers get wrong argument values

Hans_Peschke
Beginner
672 Views
Hi,

i have some problems with calling some C-functions from Fortran, if they (through an proper interface) are
- referenced through an procedure pointer, or
- procedure arguments.

For details see the code below, or download the tar.gz file in the attachement.

I compiled and debugged it with the latest Intel Fortran Compiler 11.1.072 32-Bit (the problem also occurs with version .069) on an Intel Core 2 Duo Laptop. IDB tells me, that the argument x is not proper transfered to the C function (same for rfun and ifun).

I'm not completely sure, if this code is perfectly conform with the F2003-std and if it is 100% interoperable to C, but the direct call of the C-functions (z=rfun(z) or z=ifun(z)) works, but decide self.

[cpp]#-- ctest.h --#
typedef struct interval { double INF, SUP;} interval ;

#define _PROTOTYPE(function,params) function params

_PROTOTYPE(double rfun, (double x));
_PROTOTYPE(interval ifun, (interval x));

### ctest.h ###[/cpp]
[cpp]#-- ctestr.c --#
#include "ctest.h"

double rfun(double x){
double res;

res = x*x;

return(res);
}
### ctestr.c ###[/cpp]
[bash]#-- ctesti.c --#
#include "ctest.h"

interval ifun(interval x){
interval res;

res.INF=x.INF*x.INF;
res.SUP=x.SUP*x.SUP;

return(res);
}
### ctesti.c ###[/bash]
[fortran]#-- ftest.f90 --#
module consts
use, intrinsic :: iso_c_binding
implicit none

public

integer, parameter :: dp = c_double !kind(0.0d0)

type, bind(C) :: interval
real(dp) :: inf, sup
end type
end module consts

module clib
use consts
implicit none

public

abstract interface
function rmap(x) result(res) bind(C)
use consts, only : dp
implicit none
real(dp) :: res
real(dp), value, intent(in) :: x
end function rmap
end interface

abstract interface
function imap(x) result(res) bind(C)
use consts, only : interval
implicit none
type(interval) :: res
type(interval), value, intent(in) :: x
end function imap
end interface

interface fun
function rfun(x) result(res) bind(C)
use consts, only : dp
implicit none
real(dp) :: res
real(dp), value, intent(in) :: x
end function rfun

function ifun(x) result(res) bind(C)
use consts, only : interval
implicit none
type(interval) :: res
type(interval), value, intent(in) :: x
end function ifun
end interface
end module clib

program cuftest
use consts
use clib
implicit none

call rtest()
call itest()

call rproctest(rfun)
call iproctest(ifun)

contains
subroutine rtest()
real(dp) :: x, y
integer :: i

write(*,*) 'rtest'
x = 1.0_dp
y = 0.0_dp

do i=1,5
x = fun(x)
y = fun(y)
write(*,*) i, 'x=', x
write(*,*) i, 'y=', y
end do
end subroutine rtest

subroutine itest()
type(interval) :: x, y
integer :: i

write(*,*) 'itest'
x = interval(0.0_dp, 1.0_dp)
y = interval(1.0_dp, 1.0_dp)

do i=1,5
x = fun(x)
y = fun(y)
write(*,*) i, 'x=', x
write(*,*) i, 'y=', y
end do
end subroutine itest

subroutine rproctest(f)
real(dp) :: x, y, z
integer :: i
procedure(rmap) :: f
procedure(rmap), pointer :: g

g => rfun

write(*,*) 'rproctest'
x = 2.0_dp
y = 2.0_dp
y = 2.0_dp

do i=1,5
x = f(x)
y = g(y)
z = rfun(z)
write(*,*) i, 'x=', x
write(*,*) i, 'y=', y
write(*,*) i, 'z=', z
end do
end subroutine rproctest

subroutine iproctest(f)
type(interval) :: x, y, z
integer :: i
procedure(imap) :: f
procedure(imap), pointer :: g

g => ifun

write(*,*) 'iproctest'
x = interval(1.0_dp, 2.0_dp)
y = interval(1.0_dp, 2.0_dp)
z = interval(1.0_dp, 2.0_dp)

do i=1,5
x = f(x)
y = g(y)
z = ifun(z)
write(*,*) i, 'x=', x
write(*,*) i, 'y=', y
write(*,*) i, 'z=', z
end do
end subroutine iproctest
end program cuftest
### ftest.f90 ###[/fortran]

Many thanks and Best regards

Hans
0 Kudos
4 Replies
Steven_L_Intel1
Employee
672 Views
I think your source is ok. In proctest, the compiler is ignoring the VALUE attribute specified for the argument in abstract interface rmap. I'll report this to the developers - thanks. Issue ID is DPD200155475.
0 Kudos
TimP
Honored Contributor III
672 Views
In case anyone is curious, I could show the same results on Windows, using gcc .o files linked into the ifort 11.1.065 ia32 compilation.
0 Kudos
Steven_L_Intel1
Employee
672 Views
I reproduced this on Windows easily. I also constructed a Fortran-only sample. Procedure pointers are not required to see this - simply a PROCEDURE declaration that names an abstract interface with VALUE specified for an argument will do the trick. I also found that the compiler is ignoring BIND(C) specified in an abstract interface.
0 Kudos
Steven_L_Intel1
Employee
672 Views
I expect this to be fixed in 12.0 Update 4.
0 Kudos
Reply