2

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?

francescalus
  • 30,576
  • 16
  • 61
  • 96
Stef1611
  • 1,978
  • 2
  • 11
  • 30
  • 1
    I won't repeat this question, but I can't go past without asking it: Is there a reason you really want to use the error prone c_ptr method, which is really writing C using Fortran syntax? They are different languages ... The OO method listed further down the page that you link to is the modern Fortran way of doing this. – Ian Bush Jun 07 '22 at 18:56
  • @Ian Bush. In first intention, I did not plan to use OO. For two reasons. 1) on the link I gave in my post, it is written "Usually, in the context of scientific programming, where the main .... is to use one of the previous approaches." and my program is a scientific one. And on another post (https://stackoverflow.com/q/72432427/7462275), I had the following comment "Save yourself a lot of bother and forget about OOP - a 30yr diversion down the wrong road for software construction.". But if there is no solution, I will use OO. Concerning ptr, I program in C generally so, I am aware of problems – Stef1611 Jun 07 '22 at 19:06
  • 2
    I respect the views of both Ian Bush and High Performance Mark, and in this case any "disagreement" between them is possibly more an indication of how this question could be too divisive. I also wouldn't do what you appear to be asking about (I'd approach in a very different way), so can you motivate a bit more why you want to go down this route, with a fuller example to show potential pitfalls of alternatives, or provide enough detail for other ways to be objectively judged? – francescalus Jun 07 '22 at 19:27
  • You seem to be combining two opposing ideas here. The point of a callback is that `myfoo` can be flexible, and will always work without needing to know or care about what the callback is doing. And the point of function overloading is that `myfoo` can do different things depending on what its arguments are. Combining the two means you're trying to specialise based on the arguments, while also not knowing what those arguments are. This seems counterproductive. Can you motivate why you're trying to do this? – veryreverie Jun 07 '22 at 19:39
  • @veryreverie. Not exactly, this code is simplified. There is another parameter in myfoo, a callback function. I have two functions but they have a different number of parameter. For function1(function2), the parameters are stored in a variable of type type1_t(type_2_t). It is an extension of the example where you calculate the integral of two functions that have not the same number of parameter. For example a sinus one as in the example and what you want (e.g. a third order polynomial) – Stef1611 Jun 07 '22 at 19:48
  • But the whole point of a callback is that `myfoo` doesn't need to know the number of parameters, no? Can you [edit] your question with the slightly-less-simplified version of your question? – veryreverie Jun 07 '22 at 20:31
  • 2
    You need to elaborate on the "common parts of the code". How can they be common if they are working with different type objects? Are there also common aspects of the derived types? For example, the `a` component is default real in both your type definitions. Is this intentional and significant to your question? – IanH Jun 07 '22 at 21:48
  • M'y example will be too long. I manage to do that by using three means : déclaration of two variables ( one of each type and I use only one : first PGM), with block (second pgn) and break of code into functions ( I pass the pointer to these functions where the type is well defined (third PGM). Thanks for all your comments. I hope in a future version of fortran, it will be possible to declare variables everywhere. – Stef1611 Jun 08 '22 at 05:51

1 Answers1

2

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

Federico Perini
  • 1,414
  • 8
  • 13
  • 2
    Yes, but a large party of code will be repeated. – Stef1611 Jun 07 '22 at 20:12
  • I think then that what you need is a better "abstraction" of your problem: i.e., try to find an answer to this question. how can you describe two different problems with the same interface? an ODE problem for example, will always have an ODE system function `f(t,y)` regardless of the billions of problems you can solve. It seems you need to clarify this first, before trying to turn that into code – Federico Perini Jun 08 '22 at 08:27