0

The following scenario: I have a large function library, which is programmed in Fortran and is available as a shared library for different systems (*.dll / *.dylib / *.so). From this library, some functions are now to be called in another project. However, no matter how I do it, I have no success.

I have put together a minimal example to better understand the whole thing:

Library myLib.F90:

module mylibmod
    implicit none

    public :: sayHello

    contains

        subroutine sayHello()
            !GCC$ ATTRIBUTES DLLEXPORT :: sayHello
            print*, 'Hello Fortran!'
        end subroutine sayHello

end module mylibmod

Call libCall.f90:

program libCall
    call sayHello()
    continue
end program libCall

The library is compiled using gfortran for all platforms. The calls used with Windows are: gfortran -c -o myLib.o -fPIC .\src\mylib.F90, gfortran -shared -fPIC -o mylib.dll myLib.o and gfortran -o libCall.exe -fPIC .\src\libCall.f90 mylib.dll

At the last command the linker throws me an error, that the function name can't be found in the library. [..] undefined reference to "sayhello_". However, when I take a look at the exported functions in the DLL I can find the reference:

DLL Export Viewer - reference of the function

As a next step I tried to simplify the whole thing a bit so I removed the encapsulation in a module:

myLib.f90:

subroutine sayHello()
   !GCC$ ATTRIBUTES DLLEXPORT :: sayHello
   print*, 'Hallo Fortran!'
end subroutine sayHello

Now, using the same commands, the linker finds the reference and the executable gets linked without any problem. Accordingly, the problem seems to be the encapsulation of the subroutine in the module.

Finally to my actual question: what am I doing wrong or do I have to change so that the call also works for functions in modules? - The library I want to use is completely set up in modules.

halfer
  • 19,824
  • 17
  • 99
  • 186
Bastian
  • 113
  • 1
  • 8
  • 1
    You are missing `use mylibmod` at the beginning of your `libCall` program. But... you need the `.mod` file of the module to be able to compile the program – PierU Apr 04 '23 at 11:32
  • Okay, that was actually my own stupidity then. Thank you very much for the quick hint. However, this also means that I always need all mod files of the library at least for compiling - right? – Bastian Apr 04 '23 at 11:39
  • 1
    Yes, you need to distribute the mod files along with the library. This comes with a consequence: the compiler for the calling program has to be the same as the one used for the library. – PierU Apr 04 '23 at 11:56
  • Thank you very much! - I had not known that yet. One last question: The only way around this would probably be to use a C-Interface (BIND(c)) or is there another more elegant possibility to avoid to include all mod files? – Bastian Apr 04 '23 at 12:15
  • 1
    A wrapper routine outside of the module would do, but in my opinion the `bind(C)` solution is fine. – PierU Apr 04 '23 at 12:17
  • And again thank you for your response. Probably I will go for the 'bind(C)' solution since the library provides C interfaces anyway. – Bastian Apr 04 '23 at 12:30
  • 1
    For certain argument types one could be fine with an include file with interfaces, even.if the compiler version is not the exact one, but one is then responsible for any failures it would cause. – Vladimir F Героям слава Apr 04 '23 at 12:51

0 Answers0