How to have one Fortran function with different type of parameters using c_ptr?

200 Views Asked by At

I read the section Type Casting in Callbacks of the article Fortran Best practices.

I would like to use in my program something as described in Using type(c_ptr) Pointer

But I have a problem. I give an outline of what I try to do. I hope it will be sufficient to understand. Otherwise, let me know, I will post a full example.

I have two types and I call the same subroutine with one or the other type. The first parameter of my subroutine is an integer to indicate which is the type of the second parameter (type1_t or type2_t)

type type1_t
    real :: a, b
    integer :: c
end type1_t

type type2_t
    real :: a,e
    integer :: b,c,d
end type2_t

type(type1_t) :: type1 
! ... init of type1
type(type2_t) :: type2 
! ... init of type2_t

call myfoo(1,c_loc(type_1))
call myfoo(2,c_loc(type_2))

But now, I have a problem with the declaration in myfoo because the declaration must be done in fortran before instructions.

I know that the following code does not work :

subroutine myfoo(i, params) 
  integer, intent(in) :: i
  type(c_ptr), intent(in) :: params
  
  if (i == 1) then 
    type(type1_t), pointer :: pars
  elseif (i ==2) then
    type(type2_t), pointer :: pars
  endif
  
  call c_f_pointer(params, pars)
  ! do some stuff with pars (there are common parts of code either the dummy args is type_1 or type_2). For example, the line above.

end subroutine myfoo

If I use a block construct, I will have a problem because the variable disappears at the end of the block.

How can I solve it using c_ptr?

1

There are 1 best solutions below

2
Federico Perini On

A simple way to accomplish this is to put type-specific code in two separate routines in a module, and bind them using an interface, so the compiler will pick the right subroutine based on the type of the variable provided on input:

module blabla
  private

  public :: foo

  interface foo
     module procedure foo1
     module procedure foo2
  end interface 

  contains

  subroutine foo1(params)
    type(t1) :: params
    ! Do cool stuff
  end subroutine foo1
  subroutine foo2(params)
    type(t2) :: params
    ! Do type-2 cool stuff here

  end subroutine foo2

end module blabla