Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
3 Views

C-Fortran callback interoperability with c_funptr not giving correct output

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
Highlighted
Beginner
3 Views

Sorry, just figured this out.

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
Highlighted
Valued Contributor III
3 Views

You need to apply the bind(C)

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

 

0 Kudos
Highlighted
Beginner
3 Views

Thanks, that worked.  Not

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

0 Kudos