- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You need to apply the bind(C) attribute for the callback procedure in the abstract interface.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, that worked. Not sure why the gfortran example is incorrect, it makes sense to have the BIND(C) attribute.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page