I have a C program that calls a Fortran subroutine in a static lib. This subroutine takes as argument a function pointer to a callback implemented in C. A minimal example looks like this:
Fortran code:
subroutine fortran_function(input, c_function) bind(c)
use, intrinsic :: iso_c_binding
implicit none
real(c_float), value, intent(IN) :: input
type(c_funptr), intent(IN), value :: c_function
abstract interface
subroutine callback(a, b) bind(c)
USE iso_c_binding, only: c_float, c_int
integer(c_int), intent(IN), value :: a
real(c_float), intent(IN), value :: b
end subroutine callback
end interface
procedure(callback), pointer :: c_proc
call c_f_procpointer(c_function, c_proc)
call c_proc(1_c_int, input)
if (input > 1.0) call c_proc(2_c_int, input)
end subroutine fortran_function
C code:
#include <stdio.h>
typedef void (*c_function)(int, float);
void fortran_function(float, c_function);
void callback(int a, float b)
{
printf("a=%d, b=%.1f\n", a, b);
}
int main()
{
fortran_function(0.0, &callback);
fortran_function(5.0, &callback);
}
If I compile this (Intel and MSVS on Windows) everything works fine and I get the expected output:
a=1, b=0.0
a=1, b=5.0
a=2, b=5.0
However, I ultimatley want to target a powerpc (using gfortran and gcc-variant crosscompiler). The program compiles there without warnings (-Wall) but produces the output:
a=1, b=0.0
a=2, b=0.0
a=1, b=5.0
a=2, b=5.0
This is very strange because for the first call the flow should never enter the if-body. Apparently it does so anyway, but even prints the correct value for the input.
Compiled on Ubuntu with:
powerpc-linux-gnu-gfortran test.f90 -c -Wall -pedantic
ar cr test.lib test.o
What I already checked:
- Replacing
if (input > 1.0)
withif (input > 1.0_c_float)
doesn't solve the problem - Using pass-by-reference instead by-value on the function pointer crashes instantly (on Windows it runs fine)
- Turning of optimization (on both the C and Fortran part) doesn't solve the problem
- All types are 4 byte
sizeof(real)=sizeof(real(c_float))=sizeof(integer)=sizeof(integer(c_int))
(same in C)
Does anyone have an idea what could possibly cause this problem?