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

error #7519: Required explicit interface

Gosselin__Claude
Beginner
3,962 Views

I have a function calling another one within a Fortran Dll, itself called from VB.net; therefore several functions/subroutines are exported. The project was imported in Intel Fortran 2019 from an Intel Fortran 11.1 project that ran fine. I get the following error message when I compile the project in Fortran 2019:

    error #7519: Required explicit interface for a procedure with C or STDCALL attribute is missing from original source. [

What is wrong with this in Fortran 2019 that ran Ok in Fortran 11.1 ?

Thanks for any suggestion. Claude "Azzar"

 

Here is the code:

Calling function:


    Function Conjug_P(LCond, Cote,    Pig,     TrsfMachPosn, TrsfMachNorm, TrsfMachNormInv,  &
                      Exent, DAnLtca, DepLtca, XOut,         ZOut,         AnorX,     AnorZ)

      !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: Conjug_P
      !DEC$ ATTRIBUTES DECORATE, ALIAS:'Conjug_PFT'   :: Conjug_P   

      ...

      Call ProfilP(ITrois, Cote, Pig, TrsfMachPosn, XOut, ZOut)

      ...

   Return 

   End

 

Is is the called function:

 

   Subroutine ProfilP(ICond, Cote, Pig, TrsfMach, X, Z)

      !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: ProfilP
      !DEC$ ATTRIBUTES DECORATE, ALIAS:'ProfilPFT'    :: ProfilP

     ...

   Return

   End

 

 

 

 

0 Kudos
1 Solution
IanH
Honored Contributor III
3,962 Views

The code in #3 is the same as in the original post.

Inside the procedure `Conjug_P`, what tells the compiler that ProfilP uses the STDCALL convention?

Fortran program units are based on a model of separate compilation - while compiling each program unit, the compiler only knows about other program units based on what you tell it (explicit interfaces, perhaps via modules) or what it can guess based on the procedure reference (implicit interfaces).  You should avoid the latter.  You must avoid the latter if you are doing anything remotely interesting, which includes changing the calling convention, and many, many other things.

If you must use external procedures, you can provide that information to the compiler using an interface block.

Function Conjug_P(LCond, Cote,    Pig,     TrsfMachPosn, TrsfMachNorm, TrsfMachNormInv,  &
                      Exent, DAnLtca, DepLtca, XOut,         ZOut,         AnorX,     AnorZ)

  !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: Conjug_P
  !DEC$ ATTRIBUTES DECORATE, ALIAS:'Conjug_PFT'   :: Conjug_P
  ! Presumably lots of argument declarations are here...
  
  ! Explicitly declare the interface for ProfilP in this scoping unit.
  INTERFACE
    Subroutine ProfilP(ICond, Cote, Pig, TrsfMach, X, Z)
      IMPLICIT NONE
      !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: ProfilP
      !DEC$ ATTRIBUTES DECORATE, ALIAS:'ProfilPFT'    :: ProfilP
      
      ! Declarations for ICond, Cote, etc go here.
      ...
    End SUBROUTINE ProfilP
  END INTERFACE
  
  ...
  Call ProfilP(ITrois, Cote, Pig, TrsfMachPosn, XOut, ZOut)
  ...

 

View solution in original post

0 Kudos
6 Replies
Steve_Lionel
Honored Contributor III
3,962 Views

That check is part of "Generated Interface Checking" and, I think, was added sometime after 11.0.  You haven't shown all the code, but based only on what you posted, you haven't told the caller that ProfilP uses STDCALL, hence the warning. Since you used ALIAS for ProfilP, you "took off the blade guard" of name decoration usually applied to STDCALL routines. You may think it worked ok before, but a mismatch of this nature causes stack corruption. 

0 Kudos
Gosselin__Claude
Beginner
3,962 Views

Hello Dr Fortran,

Thank you for the quick reply. Indeed, I did not show all the code - only what appears required to keep the clutter out. If you look again, unless I missed something, both methods shown have the STDCALL. Those methods that are exported need an ALIAS in the calling app to identify they come from the Fortran Dll.

So then, what should I do as I have this in several places in my project. How should I declare the attributes to avoid this error ? I looked at the sample code coming with the 2019 Fortran compiler, but there is nothing related to what I see. I also vaguely remember how much I had to dig in 2011 to get things to work with Fortran 11.1 as I pass on data structures of Real*8, Integer*4 and Character strings as arguments and these require a specific alignment.

Thank you for any info, Claude G.

 

Calling function:

    Function Conjug_P(LCond, Cote,    Pig,     TrsfMachPosn, TrsfMachNorm, TrsfMachNormInv,  &
                      Exent, DAnLtca, DepLtca, XOut,         ZOut,         AnorX,     AnorZ)

      !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: Conjug_P
      !DEC$ ATTRIBUTES DECORATE, ALIAS:'Conjug_PFT'   :: Conjug_P   

      ...

      Call ProfilP(ITrois, Cote, Pig, TrsfMachPosn, XOut, ZOut)

      ...

   Return 

   End

 

This is the called function:

   Subroutine ProfilP(ICond, Cote, Pig, TrsfMach, X, Z)

      !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: ProfilP
      !DEC$ ATTRIBUTES DECORATE, ALIAS:'ProfilPFT'    :: ProfilP

     ...

   Return

   End

0 Kudos
IanH
Honored Contributor III
3,963 Views

The code in #3 is the same as in the original post.

Inside the procedure `Conjug_P`, what tells the compiler that ProfilP uses the STDCALL convention?

Fortran program units are based on a model of separate compilation - while compiling each program unit, the compiler only knows about other program units based on what you tell it (explicit interfaces, perhaps via modules) or what it can guess based on the procedure reference (implicit interfaces).  You should avoid the latter.  You must avoid the latter if you are doing anything remotely interesting, which includes changing the calling convention, and many, many other things.

If you must use external procedures, you can provide that information to the compiler using an interface block.

Function Conjug_P(LCond, Cote,    Pig,     TrsfMachPosn, TrsfMachNorm, TrsfMachNormInv,  &
                      Exent, DAnLtca, DepLtca, XOut,         ZOut,         AnorX,     AnorZ)

  !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: Conjug_P
  !DEC$ ATTRIBUTES DECORATE, ALIAS:'Conjug_PFT'   :: Conjug_P
  ! Presumably lots of argument declarations are here...
  
  ! Explicitly declare the interface for ProfilP in this scoping unit.
  INTERFACE
    Subroutine ProfilP(ICond, Cote, Pig, TrsfMach, X, Z)
      IMPLICIT NONE
      !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE  :: ProfilP
      !DEC$ ATTRIBUTES DECORATE, ALIAS:'ProfilPFT'    :: ProfilP
      
      ! Declarations for ICond, Cote, etc go here.
      ...
    End SUBROUTINE ProfilP
  END INTERFACE
  
  ...
  Call ProfilP(ITrois, Cote, Pig, TrsfMachPosn, XOut, ZOut)
  ...

 

0 Kudos
Gosselin__Claude
Beginner
3,962 Views

Good day Steve,

Well, thanks a zillion to Dr Fortran for the detailed instructions ! it seems to do the job as I tested one function and it now compiles correctly.

I do now remember that with Fortran 11.1, I did a 2 pass compilation as I had errors, but not detailed the same way. I found out that when doing a Rebuild, if I compiled a 2nd time all the functions exhibiting the errors, I got a valid linking. I did that by creating a VBScript Macro that called each Subroutine / Function and recompiled them. That would be required only when doing a Rebuild.

But I did not find how to specify running a Macro with Fortran 2019. Would you also have a hint for this ? 

Thanks a zillion again.

Claude G.

0 Kudos
Steve_Lionel
Honored Contributor III
3,962 Views

You should not need a two-step process if you correct all the errors.

0 Kudos
jimdempseyatthecove
Honored Contributor III
3,962 Views

Claude,

You should be aware that the interfaces to your external procedures (ProfileP, etc) probably belong in a module for your Fortran procedures to use.

Jim Dempsey

0 Kudos
Reply