- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The following code works as expected with gfortran, but fails with ifort-11.1.073 (64 Bit Linux)
Sources are below
test2.c
test2f.f90
[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] Link Copied
6 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
(I had to replace the c_int32_t with 4 on Windows).
[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).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
(gdb) disassemble
Dump of assembler code for function funcptr:
0x0000000000400598
0x0000000000400599
0x000000000040059c
0x00000000004005a0
0x00000000004005a4
0x00000000004005a8
0x00000000004005ad
0x00000000004005b0
0x00000000004005b3
0x00000000004005b5
0x00000000004005ba
0x00000000004005c1
0x00000000004005c8
0x00000000004005cc
0x00000000004005cf
0x00000000004005d3
0x00000000004005d5
0x00000000004005d9
0x00000000004005db
0x00000000004005e3
0x00000000004005e4
0x00000000004005e5
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Have you been able to run test on a 64-bit Linux machine in the meantime?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I believe that this problem is fixed in Update 4.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page