Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

DLL Export as STDCALL from Fortran

Jonas_T_2
Beginner
969 Views

I am building a Dll and exporting functions and subroutines as STDCALL from Fortran. There have been and still are some difficulties to have other parts in Fortran call those exported functions aswell. It works for most of the functions but two of them simply won't link.

I decorated the functions to export with !DEC$ ATTRIBUTES DLLEXPORT, STDCALL :: <functionname>. Then I created a module to write interfaces for the exported functions, so that Fortran knows that these have STDCALL as calling convention.

The problem is with REFU and BLIND, the other functions work fine. It is unsuccessfully trying to link to _refu@36 and _blind@8.

The function MAMA is defined in the same file as BLIND, a dumpbin from the resulting obj file shows that _mama@4 and _BLIND can be found. It also shows the following linker directives, which make me wonder why the expected export for BLIND is missing:

   Linker Directives
   -----------------
   -defaultlib:ifmodintr.lib
   -export:_mama
   -export:_mama
   -export:_mama@4
   -export:_mama@4
   -defaultlib:ifconsol
   -defaultlib:libifcoremdd
   -defaultlib:libifportmd
   -defaultlib:libmmdd
   -defaultlib:MSVCRTD
   -defaultlib:libirc
   -defaultlib:svml_dispmd
   -defaultlib:OLDNAMES

fdllmodule.f90:

    module fdllmodule

    !Es folgen die Interfacedefinitionen für alle exportierten
    !Funktionen, "use fdllmodule" muss ueberall stehen, wo eine
    !der Funktionen auch innerhalb der FTN-DLL gerufen wird.
    
    Interface
    subroutine elsvor()
    !DEC$ATTRIBUTES STDCALL :: elsvor
    end subroutine elsvor
    End Interface
    
    Interface
    subroutine elsend()
    !DEC$ATTRIBUTES STDCALL :: elsend
    end subroutine elsend
    End Interface
    
    Interface
    subroutine blind(inummer,iaction)
    !DEC$ATTRIBUTES STDCALL :: blind
    !DEC$ATTRIBUTES Value :: inummer, iaction
    integer*4 inummer, iaction
    end subroutine blind
    End Interface
    
    Interface
    integer*4 function get(icommon,ivar,ilaenge,ityp,irefu,lh)
    !DEC$ATTRIBUTES STDCALL :: get
    !DEC$ATTRIBUTES Value :: icommon,ivar,ilaenge,ityp,irefu,lh
    integer*4 icommon,ivar,ilaenge,ityp,irefu
    integer*4 lh
    end function get
    End Interface
    
    Interface
    integer*4 function iget(icommon,ivar)
    !DEC$ATTRIBUTES STDCALL :: iget
    !DEC$ATTRIBUTES Value :: icommon,ivar
    integer*4 icommon,ivar
    end function iget
    End Interface    
    
    Interface
    integer*4 function janein(icommon,ivar,jcommon,jvar,iverglwert,ivergltyp,irefu)
    !DEC$ATTRIBUTES STDCALL :: janein
    !DEC$ATTRIBUTES Value :: icommon,ivar,jcommon,jvar,iverglwert,ivergltyp,irefu
    integer*4 icommon,ivar,jcommon,jvar,iverglwert,ivergltyp,irefu
    end function janein
    End Interface
    
    Interface
    subroutine put(icommon,ivar,ilaenge,ityp,irefu,lh)
    !DEC$ATTRIBUTES STDCALL :: put
    !DEC$ATTRIBUTES Value :: icommon,ivar,ilaenge,ityp,irefu
    integer*4 icommon,ivar,ilaenge,ityp,irefu
    integer*1 lh
    end subroutine put
    End Interface
    
    Interface
    subroutine iput(icommon,ivar,iwert)
    !DEC$ATTRIBUTES STDCALL :: iput
    !DEC$ATTRIBUTES Value :: icommon,ivar,iwert
    integer*4 icommon,ivar,iwert
    end subroutine iput
    End Interface
    
    Interface
    subroutine refu(irefu,ivor,icommon,ivar,jcommon,jvar,ilaenge,ix,iy)
    !DEC$ATTRIBUTES STDCALL :: refu
    !DEC$ATTRIBUTES Value :: irefu,ivor,icommon,ivar,jcommon,jvar,ilaenge,ix,iy
    integer*4 irefu,ivor,icommon,ivar,jcommon,jvar,ilaenge,ix,iy
    end subroutine refu
    End Interface
    
    Interface
    integer*4 function jprofu(iprofu,ipar1,ipar2,ipar3,ipar4)
    !DEC$ATTRIBUTES STDCALL :: jprofu
    !DEC$ATTRIBUTES Value :: iprofu,ipar1,ipar2,ipar3,ipar4
    integer*4 iprofu,ipar1,ipar2,ipar3,ipar4
    end function jprofu
    End Interface
    
    Interface
    integer*4 function jprsys(iprsys,icommon,ivar,jcommon,jvar,ilen,jlen,lh)
    !DEC$ATTRIBUTES STDCALL :: jprsys
    !DEC$ATTRIBUTES Value :: iprsys,icommon,ivar,jcommon,jvar,ilen,jlen
    integer*4 iprsys,icommon,ivar,jcommon,jvar,ilen,jlen
    integer*1 lh
    end function jprsys
    End Interface
    
    Interface
    integer*4 function inex(icommon,isprung,ivar,jzaehl,irefu,jsprung)
    !DEC$ATTRIBUTES STDCALL :: inex
    !DEC$ATTRIBUTES Value :: icommon,isprung,jzaehl,irefu,jsprung
    integer*4 icommon,isprung,ivar,jzaehl,irefu,jsprung
    end function inex
    End Interface
    
    Interface
    integer*4 function iluc(ivar,jkno,ilen,inhalt)
    !DEC$ATTRIBUTES STDCALL :: iluc
    !DEC$ATTRIBUTES Value :: ivar,jkno,ilen
    integer*4 ivar,jkno,ilen,inhalt
    end function iluc
    End Interface
    
    Interface
    integer*4 function ilu4(ivar,jkno,ilen,inhalt,i4var,jvar)
    !DEC$ATTRIBUTES STDCALL :: ilu4
    !DEC$ATTRIBUTES Value :: ivar,jkno,ilen
    integer*4 ivar,jkno,ilen,inhalt,i4var,jvar
    end function ilu4
    End Interface
    
    Interface
    subroutine elsswi(iendg,invar,memoll)
    !DEC$ATTRIBUTES STDCALL :: elsswi
    !DEC$ATTRIBUTES Value :: iendg,invar
    integer*4 iendg,invar
    integer*4 memoll(:,:)
    end subroutine elsswi
    End Interface
    
    Interface
    integer*4 function mama(ityp)
    !DEC$ATTRIBUTES STDCALL :: mama
    !DEC$ATTRIBUTES Value :: ityp
    integer*4 ityp
    end function mama
    End Interface
    
    Interface
    double precision function wwc(iwert,linie,wert)
    !DEC$ATTRIBUTES STDCALL :: wwc
    !DEC$ATTRIBUTES Value :: iwert,linie,wert
    integer*4 iwert,linie
    double precision wert
    end function wwc
    End Interface
    
    Interface
    integer*4 function iiwc(iwert,linie,lh)
    !DEC$ATTRIBUTES STDCALL :: iiwc
    !DEC$ATTRIBUTES Value :: iwert,linie
    integer*4 iwert,linie,lh
    end function iiwc
    End Interface
    
    end module

pl0put.f (works):

        SUBROUTINE IPUT(IC0,IV0,IWERT)
        !DEC$ ATTRIBUTES DLLEXPORT, STDCALL :: IPUT
        use fdllmodule, ONLY : PUT, REFU
        ...
        RETURN
        END

blind.f (BLIND does not link):

        SUBROUTINE BLIND(NR,MTY)
        !DEC$ ATTRIBUTES DLLEXPORT, STDCALL :: BLIND
        use fdllmodule
        ...
        RETURN
        END

        FUNCTION MAMA(IY)
        !DEC$ ATTRIBUTES DLLEXPORT, STDCALL :: MAMA
        use cmodule
        use, INTRINSIC :: ISO_C_BINDING
        ...
        END

elspls.f (references and does not find BLIND):

        SUBROUTINE ELSPLS
        use fdllmodule
        ...
        CALL BLIND(MIO(1),-1)
        END

 

0 Kudos
1 Solution
JVanB
Valued Contributor II
969 Views

In blind.f, could you also try adding the line

use fdllmodule, only: DELETE_ME => BLIND

in subroutine blind? Also is dummy argument lh in function iiwc correctly typed as integer*4 and not integer*1?

 

View solution in original post

0 Kudos
4 Replies
JVanB
Valued Contributor II
970 Views

In blind.f, could you also try adding the line

use fdllmodule, only: DELETE_ME => BLIND

in subroutine blind? Also is dummy argument lh in function iiwc correctly typed as integer*4 and not integer*1?

 

0 Kudos
Jonas_T_2
Beginner
969 Views

blind.f:

        SUBROUTINE BLIND(NR,MTY)
        !DEC$ ATTRIBUTES DLLEXPORT, STDCALL :: BLIND
        use fdllmodule, only: GET, IGET, JANEIN, PUT, IPUT, REFU, JPROFU,
     1  JPRSYS, INEX, ELSSWI
        ...
        END

Excluding BLIND, as you suggested, did it. Thank you very much.

As for the lh in iiwc. The answer is: I don't know. IIWC calls IWC passing LR. In IWC it is then defined as DIMENSION LH(1). There is a lot of wrong dimensions in this code. I mean using arrays as scalars happens all the time. I fixed what I ran across, while trying to figure out the linking problems.

0 Kudos
JVanB
Valued Contributor II
969 Views

Cool. But shouldn't ifort have issued a diagnostic?

 

0 Kudos
Jonas_T_2
Beginner
969 Views

I had them disabled, because it produces 1040 errors and i had to get the basics straight first.

0 Kudos
Reply