2016-08-02 151 views
2

有沒有可能讓Fortran程序在運行時加載Fortran庫?如果是這樣,是否有可能修改一個函數並僅重新編譯該庫以使原始編譯的程序在運行時在庫中調用修改的函數?Fortran動態庫,在運行時加載?

如果任何人都可以提供一個最基本的工作示例,說明如何實現這一目標將會很棒。

+2

問:在運行時是否可以讓Fortran程序加載Fortran庫?答:當然。例如,Gnu Fortran支持Linux上的動態模塊(.so)。 – paulsm4

+0

您是否在問如何創建一個動態庫? – haraldkl

+0

鏈接器是否需要新庫或將知道該怎麼做? 事情與使用.a和.so不同。 我假設你不能爲其他部分重新編譯,或者沒有源代碼? – Holmz

回答

3

這裏有一些幾個環節,可以是有益的:

  • page on rosettacode.org賦予完整的例子,詳情和Linux和MacOS
  • 討論瞭如何落實這intel forum post那個史蒂夫梅西就如何做一些建議動態加載與ifort
  • IBM page與動態庫的很好的解釋和它們的用法

如果你想要一個簡單易懂的代碼,請繼續閱讀。幾天前,我正在玩動態加載。我下面的測試代碼可能對您有所幫助。但是我在linux環境下工作,你可能不得不適應一些東西在它的OS X環境中工作。上面的rosettacode.org link會來幫助你。

下面是測試動態LIB

[[email protected]:~/test]$cat test.f90 

module test 
    use, intrinsic :: iso_c_binding 
contains 
    subroutine t_times2(v_in, v_out) bind(c, name='t_times2') 
     integer, intent(in) :: v_in 
     integer, intent(out) :: v_out 
     ! 
     v_out=v_in*2 
    end subroutine t_times2 
    ! 
    subroutine t_square(v_in, v_out) bind(c, name='t_square') 
     integer(c_int), intent(in) :: v_in 
     integer(c_int), intent(out) :: v_out 
     ! 
     v_out=v_in**2 
    end subroutine t_square 
end module test 

編譯爲

[[email protected]:~/test]$gfortran -c test.f90 
[[email protected]:~/test]$gfortran -shared -o test.so test.o 

在這裏,代碼測試程序

[[email protected]:~/test]$cat example.f90 
program example 
    use :: iso_c_binding 
implicit none 

    integer(c_int), parameter :: rtld_lazy=1 ! value extracte from the C header file 
    integer(c_int), parameter :: rtld_now=2 ! value extracte from the C header file 
    ! 
    ! interface to linux API 
    interface 
     function dlopen(filename,mode) bind(c,name="dlopen") 
      ! void *dlopen(const char *filename, int mode); 
      use iso_c_binding 
      implicit none 
      type(c_ptr) :: dlopen 
      character(c_char), intent(in) :: filename(*) 
      integer(c_int), value :: mode 
     end function 

     function dlsym(handle,name) bind(c,name="dlsym") 
      ! void *dlsym(void *handle, const char *name); 
      use iso_c_binding 
      implicit none 
      type(c_funptr) :: dlsym 
      type(c_ptr), value :: handle 
      character(c_char), intent(in) :: name(*) 
     end function 

     function dlclose(handle) bind(c,name="dlclose") 
      ! int dlclose(void *handle); 
      use iso_c_binding 
      implicit none 
      integer(c_int) :: dlclose 
      type(c_ptr), value :: handle 
     end function 
    end interface 

    ! Define interface of call-back routine. 
    abstract interface 
     subroutine called_proc (i, i2) bind(c) 
      use, intrinsic :: iso_c_binding 
      integer(c_int), intent(in) :: i 
      integer(c_int), intent(out) :: i2 
     end subroutine called_proc 
    end interface 

    ! testing the dynamic loading 
    integer i, i2 
    type(c_funptr) :: proc_addr 
    type(c_ptr) :: handle 
    character(256) :: pName, lName 

    procedure(called_proc), bind(c), pointer :: proc 
    ! 
    i = 15 

    handle=dlopen("./test.so"//c_null_char, RTLD_LAZY) 
    if (.not. c_associated(handle))then 
     print*, 'Unable to load DLL ./test.so' 
     stop 
    end if 
    ! 
    proc_addr=dlsym(handle, "t_times2"//c_null_char) 
    if (.not. c_associated(proc_addr))then 
     write(*,*) 'Unable to load the procedure t_times2' 
     stop 
    end if 
    call c_f_procpointer(proc_addr, proc) 
    call proc(i,i2) 
    write(*,*) "t_times2, i2=", i2 
    ! 
    proc_addr=dlsym(handle, "t_square"//c_null_char) 
    if (.not. c_associated(proc_addr))then 
     write(*,*)'Unable to load the procedure t_square' 
     stop 
    end if 
    call c_f_procpointer(proc_addr, proc) 
    call proc(i,i2) 
    write(*,*) "t_square, i2=", i2 
contains 
end program example 

編寫和作爲運行:

[[email protected]:~/test]$gfortran -o example example.f90 -ldl 
[[email protected]:~/test]$./example 
t_times2, i2=   30 
t_square, i2=   225 
[[email protected]:~/test]$