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

Problem linking Fortran program to Fortran DLL

F_Obermaier
Beginner
606 Views

I have a solution containing a Fortran DLL project with ~200 exported functions and a Fortran Console Application project that is supposed to test the DLL's functionality. Building the DLL project for Win32/x86 works alright, but linking the Console application for Win32/x86 leads to some LNK2019 (Unresolved external symbol) errors. Actually for 16 out of the~200.

The definition for one of functions causing linking issues is as follows:

    integer(4) function AreaSummary( pArea, iCount, fStd, fScale, fInside, fOrigin, fDestin, fThrough )
!
!   --------------------------------------------------------------------------------------------------------------------
!
!DIR$ ATTRIBUTES STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG, DECORATE, ALIAS: 'V3MatAreaSummary' :: AreaSummary
!DIR$ ATTRIBUTES VALUE  ::  iCount, fScale, fStd
        implicit none

        type(T_AREA), pointer   ::  pArea
        integer(4)              ::  iCount
        real(8)                 ::  fScale, fStd
        real(8)                 ::  fInside, fOrigin, fDestin, fThrough

        !...
    end function

 The DLLEXPORT directive is missing on purpse, the function is exported using a DEF file. The entry is:

V3MatAreaSummary=_V3MatAreaSummary@40

On the program's side the function is imported using the following interface:

interface
integer(4) function AreaSummary( pArea, iCount, fStd, fScale, fInside, fOrigin, fDestin, fThrough )
!DIR$ ATTRIBUTES DLLIMPORT, STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG, DECORATE, ALIAS: 'V3MatAreaSummary' :: AreaSummary
!DIR$ ATTRIBUTES VALUE :: iCount, fStd, fScale
use V3MatDllTypes, only: T_AREA
type(T_AREA), pointer :: pArea
integer(4) :: iCount
real(8) :: fScale, fStd
real(8) :: fInside, fOrigin, fDestin, fThrough
end function
end interface

The explicit linker error is:

V3MatTestUtility.obj : error LNK2019: unresolved external symbol __imp__V3MatAreaSummary@40 referenced in function _V3MATTESTUTILITY_mp_TESTMATRIXSUMMARY

All exported and imported functions have the same set of ATTRIBUTES directives: DLLIMPORT, STDCALL, REFERENCE, NOMIXED_STR_LEN_ARG, DECORATE and a custom ALIAS, what is wrong with this one?

0 Kudos
1 Solution
Steve_Lionel
Honored Contributor III
579 Views

What would really be helpful is if you would construct a small, buildable test case with the DLL and console application, that demonstrates the error, ZIP it and attach to a reply here. There are too many missing pieces of data to be able to guess what the problem might be.

An interesting experiment would be to remove DLLIMPORT from the directive in the console app and see what happens. Strictly speaking, DLLIMPORT is not required when calling procedures in a DLL, omitting it will add an instruction or two of overhead. I haven't used DEF files enough to know how that plays together.

View solution in original post

3 Replies
Steve_Lionel
Honored Contributor III
580 Views

What would really be helpful is if you would construct a small, buildable test case with the DLL and console application, that demonstrates the error, ZIP it and attach to a reply here. There are too many missing pieces of data to be able to guess what the problem might be.

An interesting experiment would be to remove DLLIMPORT from the directive in the console app and see what happens. Strictly speaking, DLLIMPORT is not required when calling procedures in a DLL, omitting it will add an instruction or two of overhead. I haven't used DEF files enough to know how that plays together.

F_Obermaier
Beginner
538 Views

Thank you Steve, removing DLLIMPORT from the directive makes the linker errors go away.
I will try to set up a buildable testcase anyway.

0 Kudos
Steve_Lionel
Honored Contributor III
524 Views

I think the issue here is that when you use DLLIMPORT, the compiler does the appropriate thing for when you are using an import library (the .LIB that is created when you build a DLL.) The .LIB has entry points prefixed with __imp__ that contain jumps to the appropriate offset in the corresponding DLL. When you use a DEF file, you're bypassing that mechanism and the __imp__ prefixed names do not appear.

As I wrote above, DLLIMPORT is optional when you are calling procedures in a DLL. It is required if you are accessing exported data, however, as the compiler has to generate code to do a level of indirection.

0 Kudos
Reply