cpp_bindgen icon indicating copy to clipboard operation
cpp_bindgen copied to clipboard

Passing function pointers to C functions

Open angainor opened this issue 5 years ago • 0 comments

In GHEX we need to pass a callback function from Fortran to the C++ library. The Fortran-C interface allows us to do this with the type(c_funptr) type, e.g.:

[...]
interface
     subroutine register_cb(cb) bind(c, name="register_cb")
       use iso_c_binding
       type(c_funptr), value :: cb
     end subroutine register_cb
end interface

The problem is the lack of type checking on the Fortran side, i.e., the passed function pointer is never type-checked. A solution to this is to provide 1) a callback function interface definition and 2) a wrapper function, which takes the correctly typed function pointer and calls the underlying C interface, e.g.

interface
     subroutine callback_t(rank, tag) bind(c)
         integer(c_int), value :: rank, tag
     end subroutine callback_t

     subroutine register_cb_wrapped(cb) bind(c, name="register_cb")
       use iso_c_binding
       type(c_funptr), value :: cb
     end subroutine register_cb_wrapped
end interface
contains
     subroutine register_cb(cb)
       use iso_c_binding
       procedure(callback_t), pointer :: cb

       call register_cb_wrapped(c_funloc(cb))
     end subroutine register_cb
end 

Notice that the use of a wrapper function here allows the user to pass fortran functions to the generated interface, so that he doesn't have to deal with the c_funloc interface. It would of course be possible to live without the wrapper, but the above results in a cleaner native fortran code, where the user doesn't need to know that the backend is implemented in C.

In a sense, this is similar to the strong fortran side type checking described in #39, and could maybe be implemented in a similar fashion at least when it comes to the definition of the function type.

angainor avatar Aug 19 '19 08:08 angainor