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

C-Fortran callback interoperability with c_funptr not giving correct output

Kraft__S_
Beginner
983 Views

Hi.

I am working with some Fortran - C code for passing C functions to Fortran subroutines or functions (I am interested in both).  I came across this example using the gnu compiler, and I have verified that the example works (attached both source files).  But the example does not work with the intel fortran compiler (2018, running on opensuse linux).  Instead of the given argument (c_double type) being displayed, a value of 0.00000... is displayed.

https://gcc.gnu.org/onlinedocs/gfortran/Working-with-Pointers.html

 

C- Code:

#include <stdio.h>

/* Procedure implemented in Fortran.  */
void get_values (void (*)(double));

/* Call-back routine we want called from Fortran.  */
void print_it (double x){
  printf ("Number is %f.\n", x);
}

int main(){
    /* Call Fortran routine and pass call-back to it.  */
   get_values (&print_it);
   return 0;

}

 

Fortran Code:

MODULE m
  IMPLICIT NONE

  ! Define interface of call-back routine.
  ABSTRACT INTERFACE
    SUBROUTINE callback (x)
      USE, INTRINSIC :: ISO_C_BINDING
      REAL(KIND=C_DOUBLE), INTENT(IN), VALUE :: x
    END SUBROUTINE callback
  END INTERFACE

CONTAINS

  ! Define C-bound procedure.
  SUBROUTINE get_values (cproc) BIND(C)
    USE, INTRINSIC :: ISO_C_BINDING
    TYPE(C_FUNPTR), INTENT(IN), VALUE :: cproc
    REAL(KIND=C_DOUBLE) :: VAR3
    PROCEDURE(callback), POINTER :: proc

    ! Convert C to Fortran procedure pointer.
    CALL C_F_PROCPOINTER (cproc, proc)

    ! Call it.
    CALL proc (1.0_C_DOUBLE)
    CALL proc (-42.0_C_DOUBLE)
    CALL proc (18.12_C_DOUBLE)
    
    VAR3 = 35
    CALL proc (VAR3)
    PRINT *, VAR3
    
  END SUBROUTINE get_values
END MODULE m

 

Results: gfortran

Number is 1.000000.
Number is -42.000000.
Number is 18.120000.
Number is 35.000000.
   35.000000000000000

Results: ifort

Number is 0.000000.
Number is 0.000000.
Number is 0.000000.
Number is 0.000000.
   35.0000000000000

 

Rather new to Fortran, please forgive my lack of correct terminology and knowledge of this language.  Thanks.

0 Kudos
3 Replies
Kraft__S_
Beginner
983 Views

Sorry, just figured this out.  Needed to append BIND(C) to the SUBROUTINE Interface declaration:

  ! Define interface of call-back routine.
  ABSTRACT INTERFACE
    SUBROUTINE callback (x) BIND(C)
      USE, INTRINSIC :: ISO_C_BINDING
      REAL(KIND=C_DOUBLE), INTENT(IN), VALUE :: x
    END SUBROUTINE callback
  END INTERFACE

 

0 Kudos
FortranFan
Honored Contributor III
983 Views

You need to apply the bind(C) attribute for the callback procedure in the abstract interface.

 

0 Kudos
Kraft__S_
Beginner
983 Views

Thanks, that worked.  Not sure why the gfortran example is incorrect, it makes sense to have the BIND(C) attribute.

0 Kudos
Reply