Topic: Fortran DLL called by SF project

Jeff,

Would you clarify the appropriate way to create and call a SF shared DLL library that uses AppGraphics and how it should be called from a SF project?

Example something like:

        Subroutine DrawLine( XD,YD,ND,cTitle,cMenu )

            USE appgraphics

            implicit none

            !GCC$ ATTRIBUTES dllexport, stdcall :: DrawLine

            INTEGER, PARAMETER :: I2B = KIND(4)
            INTEGER, PARAMETER :: SP = KIND(1.0E0)

            character(*) :: cTitle
            character(*) :: cMenu
            integer(I2B), intent(in) :: ND
            real(SP), intent(in) :: XD(ND),YD(ND)
    ....
    ....
    CONTAINS

    Subroutine move(x,y)
    ...
    end subroutine

    end Subroutine DrawLine

Compiler Flags -

target name: DrawLine.dll

Shared Library [x]

Static Linking: [x] All Static

Fortran Compiler: -fno-underscoring

Linker: -static -mrtd

Is this correct or are other options needed?

Frank

Re: Fortran DLL called by SF project

Frank,

It depends on exactly what you're trying to achieve.  If you were trying to call this routine from, for example, Excel or Visual Basic, then you've almost gotten everything right.  You would still need to mark this routine as BIND(C)

However, if I understand you correctly, you plan to call this DLL from another Fortran program compiled by Simply Fortran.  If that is the case, you can do away with much of the complications.  First, you do not need to add the !GCC$ ATTRIBUTES line; that line is necessary to specify the symbols being exported and the calling convention.  By default, gcc should export everything, though, and the calling convention simply isn't important if you're linking a Simply Fortran DLL with a Simply Fortan EXE.  Both would use the same calling convention.

You should also remove the flag -fno-underscoring from the Fortran compiler flags.  That flag basically tells the compiler that it shouldn't decorate any function names with a trailing underscore, a common, but not standard, convention for Fortran compilers.  However, again, since you'll be calling from another Fortran EXE, we don't need to remove the underscore.  In fact, not removing it may cause it to not link properly.

Next, on the Linking tab in the Project Options dialog, be sure that "Build Import Library" is checked.  This option causes the compiler to generate a "<mylibraryname>.a" file, named similar to the DLL itself, that can be used in another project to link against.  This step can make building your EXE drastically easier because the compiler will use the ".a" file for linking, and will use the DLL at runtime.

Let me know if I understand everything correctly.  Creating and linking against a DLL created in Simply Fortran from a Simply Fortran EXE is actually quite easy.  Matters only become complicated when you wish to call the DLL from another language, especially if everything is 32-bit.

Jeff Armstrong
Approximatrix, LLC

Re: Fortran DLL called by SF project

Hi Jeff,

Thank you for your reply.  I thought your explanation was quite clear until I tried to implement what I had thought you explained.

I removed the Fortran Compiler flag as suggested: -fno-underscoring, and added to the linker option: Import Library: [x]
The target name used was libDrawLine.dll and once compiled (64-bit Windows 7) the file libDrawLine.dll.a was created correctly.

Compiler Flags -
target name: libDrawLine.dll
Shared Library [x]
Static Linking: [x] All Static
Import Library: [x]
Fortran Compiler:
Linker: -static -mrtd

To use the import dll library in other SF projects, to the linker options was added the flag -lDrawLine.dll telling the linker to load and link to libDrawLine.a which in turn directs the resultant complied exe project to use libDrawLine.dll.

Unfortunately, SF did not recognize libDrawLine.dll.a. I also tried adding to the linker options Linker: -static -mrtd -implib=libDrawLine.dll and then tried adding -libDrawLine.dll.a without the 'implib='.  That didn't work either.

Finally, I decided to do away with the linker options for the lib altogether and load and add the file libDrawLine.dll.a to the Project outline with the main project file MyDrawLine.f90 and try to compile them.  It worked perfectly.  The program file MyDrawLine.exe was created and linked to the dll library libDrawLine.dll and executed as expected.

So my question is, what was I doing wrong that wouldn't allow the compiler to recognize the libDrawLine.dll.a file?

As always, I appreciate your feedback.

Thanks,
Frank

Re: Fortran DLL called by SF project

Frank,

The only thing I can think of as to why the import library didn't work when using the -lDrawLine.dll flag is that you didn't add the necessary directory to the list of library search directories.  Even the project directory has to be manually added.  Otherwise, it will only ever check the default system and add-on library directories.

However, you can of course include the DLL in your project directly, and the linker is usually smart enough to deal with it properly.  There's no need to use the import library if you don't need to.  I'm glad what you've tried is working!

Jeff Armstrong
Approximatrix, LLC

Re: Fortran DLL called by SF project

Jeff,

Thank you for your advice.  I find placing the SF compiled DLL (Fortran source using AppGraphics) in the Project Outline with all my other *.f90 files the easiest way to just compile and link all the project files at once.  This approach works perfectly when the DLL is call from a Fortran program that does not USE AppGraphics.

However, I encounter a problem when attempting to call the same dll subroutine (e.g., DrawLine() ) in a SF program that uses AppGraphics extensively to create a main menu of display options.  The errors received are -

Error: Class already exists.
Error: Drawing operation was attempted when there was no current window.

If anything obvious comes to mind that might fix this problem, please let me know.

Any suggestions, however obscure, may be useful.

Frank