I’m trying to return an opaque type from a C-routine using void* in combination with c_ptr. This is discussed in Type(c_ptr) and void *, but not there is no solution for returning void* from C to use it in Fortran.
program return_void_star
use ISO_C_binding
implicit none
interface
subroutine f(v,ctx) bind(c)
use ISO_C_binding
integer, intent(in) :: v
type(c_ptr), value :: ctx
! type(c_ptr), intent(out) :: ctx ! does not work either
end subroutine f
end interface
type(c_ptr) :: pt
integer, pointer :: my_ctx
!allocate(my_ctx) ! does not help
call f(42,pt)
call c_f_pointer(pt,my_ctx)
print*, my_ctx
end program return_void_star
For this to work, your C routine has to accept a double pointer (void **) instead. Then, remove the value attribute of the pointer dummy argument in your interface. Currently, you pass the pointer argument as a copy but change the pointer address in the C routine. You can test it by initialising the pointer in Fortran with c_null_ptr and check the address after calling the interface. (At the moment, it should be still c_null_ptr afterwards).
program return_void_star
use ISO_C_binding
implicit none
interface
subroutine f(v,ctx) bind(c)
use ISO_C_binding
integer, intent(in) :: v
type(c_ptr) :: ctx
end subroutine f
end interface
type(c_ptr) :: pt
integer, pointer :: my_ctx
call f(42,pt)
call c_f_pointer(pt,my_ctx)
print*, my_ctx
end program return_void_star
Especially when allocating memory/returning a new object, another solution is via a function’s return argument, it makes it a bit easier to read and there is guaranteed interoperability between C and Fortran (I guess the return argument is by value, but standard experts will know that better):
ctx* get_context(int *v) { return (ctx*) v; }
interface
type(c_ptr) function get_context(v) bind(C,name='get_context')
import c_int,c_ptr
integer(c_int), intent(inout) :: v
end function
end interface
Note that int * typically means intent(inout) by reference; while const int *v typically means intent(in) by reference. if you set intent(in), the Fortran compiler may dangerously optimize the calls, with unintended consequences