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

Bugreport: Function pointers and Fortran 2003 C interoperability

adrianinteldev
Beginner
1,160 Views
The following code works as expected with gfortran, but fails with ifort-11.1.073 (64 Bit Linux)

[bash]icc-11.1.073 -O0 -ggdb -c test2.c -o test2.o
ifort-11.1.073 -nofor-main -O0 -ggdb test2f.f90 test2.o -o test2
./test2
Expecting 16: i = -7400[/bash]


Sources are below

test2.c
[cpp]#include 
#include 

void funcptr(void(*fptr) (int32_t));  

void test2(int32_t i) {
  printf("Expecting 16: i = %d\n", i);
}

int main(){  
  funcptr(test2);  
  return 1;  
} [/cpp]


test2f.f90
[fortran]subroutine funcptr(c_test2) bind(c)  
  use, intrinsic :: iso_c_binding  
  interface
     subroutine test2(intval) bind(c)
       use iso_c_binding
       integer(c_int32_t), value :: intval
     end subroutine test2
  end interface
 
  type(c_funptr), value :: c_test2
  procedure(test2), pointer :: f_test2
  integer(c_int32_t) :: localint
 
  call c_f_procpointer(c_test2, f_test2)
  localint = 16
   
  call f_test2(localint)
  return
end subroutine funcptr[/fortran]

0 Kudos
6 Replies
Steven_L_Intel1
Employee
1,160 Views
I will admit I'm not a C expert, but isn't your C code just passing the address of test2 rather than a pointer containing the address of test2? The latter is what your Fortran code is expecting. When I try this on Windows, at least (that's what I have easier access to), that's what MSVC does. If I replace your Fortran code with this, it works:

[fortran]subroutine funcptr(c_test2) bind(c)  
  use, intrinsic :: iso_c_binding  
  interface
     subroutine c_test2(intval) bind(c)
       use iso_c_binding
       integer(4), value :: intval
     end subroutine c_test2
  end interface
 
  integer(4) :: localint
 
  localint = 16
   
  call c_test2(localint)
  return
end subroutine funcptr[/fortran]

(I had to replace the c_int32_t with 4 on Windows).
0 Kudos
adrianinteldev
Beginner
1,160 Views
Thanks for the quick reply!

No, I think this doesn't go far enough. In my understanding both test2 and &test2 are valid options to get the address of the function (strange, I know, but see for example http://www.cprogramming.com/tutorial/function-pointers.html). As you can see in the pasted output, the function is actually being called, only the arguments are scrambled.

Replacing c_int32_t with 4 seems not make a difference on my machine.

Could you try to run the test on 64-bit Linux, too? It seems to me like an ABI issue.
0 Kudos
adrianinteldev
Beginner
1,160 Views
From the assembler output I think I can see what happens:

(gdb) disassemble
Dump of assembler code for function funcptr:
0x0000000000400598 : push %rbp
0x0000000000400599 : mov %rsp,%rbp
0x000000000040059c : sub $0x20,%rsp
0x00000000004005a0 : mov %rdi,-0x20(%rbp)
0x00000000004005a4 : lea -0x20(%rbp),%rax
0x00000000004005a8 : mov $0x600f90,%edx
0x00000000004005ad : mov %rax,%rdi
0x00000000004005b0 : mov %rdx,%rsi
0x00000000004005b3 : xor %eax,%eax
0x00000000004005b5 : callq 0x400890
0x00000000004005ba : movl $0x10,-0x8(%rbp)
0x00000000004005c1 : mov 0x2009c8(%rip),%rax # 0x600f90
0x00000000004005c8 : lea -0x8(%rbp),%rdx
0x00000000004005cc : mov %rdx,%rdi
0x00000000004005cf : mov %rax,-0x10(%rbp)
0x00000000004005d3 : xor %eax,%eax
0x00000000004005d5 : mov -0x10(%rbp),%rdx
0x00000000004005d9 : callq *%rdx
0x00000000004005db : movq $0x0,-0x18(%rbp)
0x00000000004005e3 : leaveq
0x00000000004005e4 : retq
0x00000000004005e5 : nop
End of assembler dump.



The problem is that instead of the value (as specified by the interface), the address of the localint is written into register rdi, which is where the C function expects parameter 0.
0 Kudos
Steven_L_Intel1
Employee
1,160 Views
Unfortunately I will not be able to try it in that environment for a while. One of my colleagues, I am sure, can do so.
0 Kudos
adrianinteldev
Beginner
1,160 Views
Have you been able to run test on a 64-bit Linux machine in the meantime?
0 Kudos
Steven_L_Intel1
Employee
1,160 Views
I believe that this problem is fixed in Update 4.
0 Kudos
Reply