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

error LNK2001: unresolved external symbol when Migrating from IFORT to IFX

Chaudhary__Krishna
2,536 Views

Hi,

We are in the process of migrating our codes from IFORT compiler to IFX compiler. We encountered error LNK2001: unresolved external symbol SETDLLEXTRAINFO and 

error LNK2001: unresolved external symbol GETDLLEXTRAINFO for the interface of subroutines in the DLL. The interface declaration is as follows:

      Interface

        Subroutine getDLLExtraInfo( iMod , aString, iInfo, rInfo )
        Character (Len=255) aString
        Integer iMod, iInfo(10)
        Double Precision rInfo(10)

!DEC$ ATTRIBUTES DLLExport, StdCall, reference  :: getDLLExtraInfo
        End Subroutine getDLLExtraInfo

        Subroutine setDLLExtraInfo( iInfo, rInfo )
        Integer          :: iInfo(10)
        Double Precision :: rInfo(10)

!DEC$ ATTRIBUTES DLLExport, StdCall, reference  :: setDLLExtraInfo
        End Subroutine setDLLExtraInfo
      End Interface

We tried with both Intel oneAPI Compiler 2023.1.0 and 2024.1.0 as well. The latest version also didn't help much. Any help or suggestions will be greatly appreciated. Thank you.

Labels (1)
0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
2,404 Views

Thanks - I can reproduce the problem using IFX but not IFORT. The really curious thing is that the error message names Test_1.exp as the referencing file, and you don't have such a file. This appears to be an object file created by IFX for the purpose of naming DLLEXPORTed names, and it is failing to downcase the procedure names. This is a bug, or perhaps (see next paragraph), the bug is that IFX isn't just ignoring DLLEXPORT here as it should.

Your code has a bug as well, that being putting DLLEXPORT in the interface to the procedures. DLLEXPORT in an interface doesn't make any sense, and it's not correct for what you're doing here, since these routines are not being linked to from a DLL, but rather you're using GetProcAddress to find these routines in a DLL you've presumably loaded with LoadLibrary. Take out the DLLEXPORT in the directives.

View solution in original post

0 Kudos
10 Replies
Steve_Lionel
Honored Contributor III
2,528 Views

I'll note that one of the effects of the STDCALL attribute is to downcase the external symbol name. Given that ifx is x64-only, the use of @n suffixes doesn't apply, but the default of pass-by-value does. That the errors relate to upcased symbol names suggests that either the interface was not seen or that ifx is not properly interpreting the STDCALL attribute. I tried a test case to see what happened and it worked as I expected.

If you could provide a complete test case, we'd be glad to look at it.

0 Kudos
Chaudhary__Krishna
2,482 Views

Thank you Steve for your suggestions. I tried with lowercase symbol name with no success (tried with 2023.1.0 only though). 

...
!DEC$ ATTRIBUTES DLLExport, StdCall, reference  :: getdllextrainfo
...
!DEC$ ATTRIBUTES DLLExport, StdCall, reference  :: setdllextrainfo
...

If I change the 'reference' to 'value', I get 

Error		error #6445: A dummy argument is required in this context.   [GETDLLEXTRAINFO]		
Error		error #6445: A dummy argument is required in this context.   [SETDLLEXTRAINFO]

If I provide the dummy arguments there, I get other errors. 

I looked into the DLL routines (Fortran) and there also the STDCALL symbol names have a mixed case (as I have shown in my original post), but it doesn't throw any errors there. The DLL projects compile successfully. Not sure why, but the main kernel throws LNK2001 errors.

 

 

0 Kudos
Chaudhary__Krishna
2,474 Views

The subroutine which calls these routines is as shown below (I have removed some sensitive information).

 

      Subroutine Get_Set_Extra( p_DLL, iSet )
      use kernel32
	  ! I removed some sensitive info from this routine
      implicit None

      integer (kind = int_ptr_kind()), intent(in):: p_DLL
      integer, intent(in):: iSet

      integer          :: iInfo(10)
      double precision :: rInfo(10)

      Interface

        Subroutine getDLLExtraInfo( iMod , aString, iInfo, rInfo )
        Character (Len=255) aString
        Integer iMod, iInfo(10)
        Double Precision rInfo(10)

!DEC$ ATTRIBUTES DLLExport, StdCall, reference  :: getdllextrainfo

        End Subroutine getDLLExtraInfo

        Subroutine setDLLExtraInfo( iInfo, rInfo )
        Integer          :: iInfo(10)
        Double Precision :: rInfo(10)

!DEC$ ATTRIBUTES DLLExport, StdCall, reference  :: setdllextrainfo

        End Subroutine setDLLExtraInfo
      End Interface


      Integer (kind = int_ptr_kind()) p_Func1, p_Func2
      Integer iErr, iMod
      pointer (p_Func1,getDLLExtraInfo)
      pointer (p_Func2,setDLLExtraInfo)

      p_Func1=getprocaddress(p_DLL,"getdllextrainfo"C)
      if ( p_Func1 /= 0 ) then
	    !... removed some code
        Call getDLLExtraInfo(iMod , aString, iInfo, rInfo)
      end if
      p_Func2=getprocaddress(p_DLL,"setdllextrainfo"C)
      if ( p_Func2 /= 0 ) then
	    !... removed some code
        Call setDLLExtraInfo( iInfo, rInfo )
		!... removed some code
      end if

      End Subroutine Get_Set_Extra

 

0 Kudos
Steve_Lionel
Honored Contributor III
2,465 Views

Can you attach a ZIP file with just minimal sources that demonstrate the problem? Also give the commands you use to build.  You can remove everything other than declarations and the calls.

Specifying a lowercase name after the :: in the directive has no effect, as Fortran is normally case-insensitive. 

0 Kudos
Chaudhary__Krishna
2,459 Views

Hi Steve,

Kindly find attached a very simple console example. I haven't changed any project settings. Just created a console project with all default settings. When I use the Intel Fortran Compiler Classic (IFORT), the program compiles fine. When I change it to Intel Fortran Compiler (IFX), it throws the exact same LNK2001 errors that I have reported in my original post. I can reproduce the error. I hope this will be helpful.

 

0 Kudos
Steve_Lionel
Honored Contributor III
2,405 Views

Thanks - I can reproduce the problem using IFX but not IFORT. The really curious thing is that the error message names Test_1.exp as the referencing file, and you don't have such a file. This appears to be an object file created by IFX for the purpose of naming DLLEXPORTed names, and it is failing to downcase the procedure names. This is a bug, or perhaps (see next paragraph), the bug is that IFX isn't just ignoring DLLEXPORT here as it should.

Your code has a bug as well, that being putting DLLEXPORT in the interface to the procedures. DLLEXPORT in an interface doesn't make any sense, and it's not correct for what you're doing here, since these routines are not being linked to from a DLL, but rather you're using GetProcAddress to find these routines in a DLL you've presumably loaded with LoadLibrary. Take out the DLLEXPORT in the directives.

0 Kudos
Chaudhary__Krishna
2,395 Views

Thanks, Steve. Yes, the problem only occurs with IFX, not with IFORT. Test_1 is the project as well as the solution name. The main program lies in Test_1.f90 and that file is included as well (Zip includes everything in that folder - Test_STDCALL). Thank you for your testing and pointing out the bug. If I take out the DLLEXPORT in the directives, it does compile successfully. I'll check if there is any side effect in our testcases due to taking out DLLEXPORT in the directives.

0 Kudos
Steve_Lionel
Honored Contributor III
2,388 Views

I know the project is named Test_1 - I was referring to Test_1.exp, a file that is created during the build, not part of your project.

For what it's worth, DLLIMPORT in an interface is a thing, but you don't need it either. DLLEXPORT is right out.

0 Kudos
Chaudhary__Krishna
2,376 Views

I have no idea about Test_1.exp file.

0 Kudos
Steve_Lionel
Honored Contributor III
2,339 Views

As I said, the .exp file is created by the build process, not by you. In the case of DLLEXPORT appearing in an interface block, the compiler should simply ignore it as the only place DLLEXPORT should appear is in the source of the procedure being exported.

Reply