# Iso\_c\_binding: callbacks, gfortran and flang

**URL:** <https://fortran-lang.discourse.group/t/iso-c-binding-callbacks-gfortran-and-flang/10663>\
**Category:** Uncategorized\
**Created:** [January 25, 2026, 12:36pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-callbacks-gfortran-and-flang/10663 "2026-01-25T12:36:40Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![HugoMVale](https://avatars.discourse-cdn.com/v4/letter/h/e19adc/32.png) [@HugoMVale](https://fortran-lang.discourse.group/u/HugoMVale)\
**Post date:** [January 25, 2026, 12:36pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-callbacks-gfortran-and-flang/10663/1 "2026-01-25T12:36:40Z")

</div>

I maintain a Fortran library with a C interface, so that it can be called from Python, etc.  
The library compiles with `gfortran`, but not with `flang`.

The code below is a minimal example of the approach I use to build the C-API. The tricky part is the handling of the callbacks.  
`gfortran` apparently considers that the C-callback interface matches the Fortran-callback and does the “right” thing. `flang`, on the other hand, is strict and deems the interfaces incompatible because the Fortran interface does not have the `bind(c)` attribute.

I can “solve” the problem by adding `bind(c)` to `func_t`. However, then `flang` forces me to add `bind(c)` to the pure fortran callbacks, which is not very fortranic.

How can I address this issue in a proper manner without constraining the Fortran usage to the specific requirements of the C-API?

```fortran
module lib
  use iso_c_binding, only: c_int, c_float, c_funptr, c_f_procpointer, c_funloc
  implicit none

  abstract interface
    subroutine func_t(n, x, res)
    ! Interface for Fortran callback
      integer, intent(in) :: n
      real, intent(in) :: x(n)
      real, intent(out) :: res(n)
    end subroutine func_t
    
    subroutine func_c_t(n, x, res) bind(c)
    ! Interface for C callback
    ! Identical to func_t but with C types and bind(c)
      import :: c_int, c_float
      integer(c_int), intent(in) :: n
      real(c_float), intent(in) :: x(n)
      real(c_float), intent(out) :: res(n)
    end subroutine func_c_t
  end interface
  
contains

  subroutine norm_func(f, n, x, fnorm)
  ! Main Fortran algorithm using Fortran callback
  ! Here just a trivial example computing the 2-norm of f(x)
    procedure(func_t) :: f
    integer, intent(in) :: n
    real, intent(in) :: x(n)
    real, intent(out) :: fnorm
    real :: res(n)

    call f(n, x, res)
    fnorm = norm2(res)

  end subroutine norm_func

  subroutine norm_func_c(f, n, x, fnorm) bind(c)
  ! C-wapper to main algorithm using a C callback
    procedure(func_c_t) :: f
    integer(c_int), intent(in) :: n
    real(c_float), intent(in) :: x(n)
    real(c_float), intent(out) :: fnorm

    ! gfortran works fine with or without this explicit conversion
    ! flang complains regardless
    type(c_funptr) :: fp
    procedure(func_t), pointer :: fptr
    fp = c_funloc(f)
    call c_f_procpointer(fp, fptr)
    
    call norm_func(f, n, x, fnorm)

  end subroutine norm_func_c

end module lib

program test
  use lib
  implicit none

  integer, parameter :: n = 3
  real :: x(n), fnorm
  integer :: i

  x = 3.0
  call norm_func(myfunc, n, x, fnorm)
  print *, fnorm

contains

  subroutine myfunc(n, x, res)
    integer, intent(in) :: n
    real, intent(in) :: x(n)
    real, intent(out) :: res(n)
    integer :: i
    res = x ** 2
  end subroutine myfunc

end program test

```

---

<div class="post-metadata">

**Author:** ![HugoMVale](https://avatars.discourse-cdn.com/v4/letter/h/e19adc/32.png) [@HugoMVale](https://fortran-lang.discourse.group/u/HugoMVale)\
**Post date:** [January 25, 2026, 3:14pm UTC](https://fortran-lang.discourse.group/t/iso-c-binding-callbacks-gfortran-and-flang/10663/2 "2026-01-25T15:14:44Z")

</div>

I’ve solved my own question! 🙂

One must receive the C-callback as generic `c_funptr` and then cast it to the desired Fortran procedure pointer using `call c_f_procpointer`.

```fortran
module lib
  use iso_c_binding, only: c_int, c_float, c_funptr, c_f_procpointer
  implicit none

  abstract interface
    subroutine func_t(n, x, res)
    ! Interface for Fortran callback
      integer, intent(in) :: n
      real, intent(in) :: x(n)
      real, intent(out) :: res(n)
    end subroutine func_t
  end interface
  
contains

  subroutine norm_func(f, n, x, fnorm)
  ! Main Fortran algorithm using Fortran callback
  ! Here just a trivial example computing the 2-norm of f(x)
    procedure(func_t) :: f
    integer, intent(in) :: n
    real, intent(in) :: x(n)
    real, intent(out) :: fnorm
    real :: res(n)

    call f(n, x, res)
    fnorm = norm2(res)

  end subroutine norm_func

  subroutine norm_func_c(fp, n, x, fnorm) bind(c)
  ! C-wapper to main algorithm using a C callback
    type(c_funptr), value :: fp
    integer(c_int), intent(in) :: n
    real(c_float), intent(in) :: x(n)
    real(c_float), intent(out) :: fnorm

    procedure(func_t), pointer :: f
    
    call c_f_procpointer(fp, f)
    
    call norm_func(f, n, x, fnorm)

  end subroutine norm_func_c

end module lib

program test
  use lib
  implicit none

  integer, parameter :: n = 3
  real :: x(n), fnorm
  integer :: i

  x = 3.0
  call norm_func(myfunc, n, x, fnorm)
  print *, fnorm

contains

  subroutine myfunc(n, x, res)
    integer, intent(in) :: n
    real, intent(in) :: x(n)
    real, intent(out) :: res(n)
    integer :: i
    res = x ** 2
  end subroutine myfunc

end program test

```
