lbjx
lbjx

Reputation: 205

How to pack fortran interface as a standalone module

I want to package the fortran interface as a standalone library, something similar head file in c/c++. Here is my code. The problem is that i want to call the "hello" subroutine to run the "hello" subroutine. can anyone help me out?

I want to put Interface and set_callback,invoke_callback as a standalone module file.

MODULE DEMO
  INTERFACE
    SUBROUTINE callback_prototype(callbackID)
        CHARACTER(*) :: callbackID
    END SUBROUTINE callback_prototype
  END INTERFACE

  PROCEDURE( callback_prototype ), POINTER :: f_ptr => NULL()

  CONTAINS
  SUBROUTINE set_callback(func)
     IMPLICIT NONE
     EXTERNAL :: func

      f_ptr => func
      call HELLO
  END SUBROUTINE

  SUBROUTINE invoke_callback(callbackID)
      CHARACTER(*) :: callbackID
      if (associated(f_ptr)) call f_ptr(callbackID)
  END SUBROUTINE

  SUBROUTINE HELLO

  IMPLICIT NONE

  Dosomething

  END SUBROUTINE
END MODULE

Upvotes: 1

Views: 487

Answers (1)

haraldkl
haraldkl

Reputation: 3819

This would be easily possible with submodules, unfortunately they are not widely available. Thus, I guess the current solution would be to use "hello" as an external function with an implicit interface and putting it into a different file.

Update: Some example based on your code.

subroutine HELLO
  implicit none

  write(*,*) 'HELLO'

end subroutine HELLO

module demo
  implicit none

  interface
    subroutine callback_prototype(callbackID)
      character(*) :: callbackID
    end subroutine callback_prototype
  end interface

  procedure(callback_prototype), pointer :: f_ptr => NULL()

contains

  subroutine set_callback(func)
    procedure(callback_prototype) :: func
    external :: HELLO

    f_ptr => func
    call HELLO()
  end subroutine set_callback

  subroutine invoke_callback(callbackID)
    character(*) :: callbackID
    if (associated(f_ptr)) call f_ptr(callbackID)
  end subroutine invoke_callback

end module demo

program test_demo
  use demo

  implicit none

  write(*,*) 'small program'
end program test_demo

Putting this into a file test.f90, and running "gfortran test.f90" produces an executable. Of course, if you want to have that stuff separated you would rather put each part in separate files. You then have to ensure, that the object file containing "hello" is included during link time. And as pointed out by Vladimir_F, you can use an interface declaration to equip the routine with an explicit interface, where you are calling it.

2nd update:

If you put these into three different files

  • hello.f90
  • demo.f90
  • test.f90

You should be able to compile an executable out of them like this:

gfortran -c demo.f90 hello.f90 test.f90
gfortran *.o

The first line creates the object files, while the second links them together. Note, that order is important, the module information for demo.f90 needs to be available before compiling test.f90.

Upvotes: 1

Related Questions