Fortran interop with C function pointer wrong results

205 Views Asked by At

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) with if (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?

0

There are 0 best solutions below