fortranlinker-errorsgfortranldd

Linker error in calling a subroutine of a library


I've created a simple shared library in Fortran and used it in a test program. The library module contains a subroutine in a file named my_module.f90 that is:

  ! my_module.f90

   module my_module

       contains

       subroutine my_subroutine()
          print *, "Hello from my_subroutine!"
       end subroutine my_subroutine

   end module my_module

I compiled it, using the below command:

gfortran -shared -fPIC my_module.f90 -o libmy_library.so

I created a file named test_program.f90:

   ! test_program.f90

    program main
       implicit none
       external :: my_subroutine
       call my_subroutine()
    end program main

when I compile the test program with the shared library:

gfortran test_program.f90 -o test_program -L. -lmy_library

it failed due to

undefined reference to `my_subroutine_'
collect2: error: ld returned 1 exit status

How can this issue be resolved?


Solution

  • Because of name mangling, your subroutine has different name in your .so file:

    [gmt@arch ~]$ nm libmy_library.so 
                     w __cxa_finalize@GLIBC_2.2.5
    0000000000004020 d __dso_handle
    0000000000003dd8 d _DYNAMIC
    00000000000011d4 t _fini
                     U _gfortran_st_write_done@GFORTRAN_8
                     U _gfortran_st_write@GFORTRAN_8
                     U _gfortran_transfer_character_write@GFORTRAN_8
    0000000000003fe8 d _GLOBAL_OFFSET_TABLE_
                     w __gmon_start__
    0000000000002028 r __GNU_EH_FRAME_HDR
    0000000000001000 t _init
                     w _ITM_deregisterTMCloneTable
                     w _ITM_registerTMCloneTable
    0000000000001139 T __my_module_MOD_my_subroutine
                     U __stack_chk_fail@GLIBC_2.4
    0000000000004028 d __TMC_END__
    

    you can use BIND(C,... to resolve this.

    subroutine my_subroutine() BIND(C,NAME="my_subroutine_")
       print *, "Hello from my_subroutine!"
    end subroutine my_subroutine 
    

    EDIT: Don't do this. I added the nm output just to show name mangling. It's better to use USE my_module or USE my_module, ONLY: my_subroutine.