- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a Fortran console application which is trying to import a routine from a Fortran dll. I'm getting the following error message when linking.
error LNK2019: unresolved external symbol __imp__USELOG referenced in function _MAIN__
The interface for the routine is:
INTERFACE
SUBROUTINE USELOG(logname, progname, version)
!DEC$ ATTRIBUTES, ALIAS:'USELOG' :: USELOG
!DEC$ ATTRIBUTES DLLIMPORT :: USELOG
CHARACTER(LEN=26) :: logname
CHARACTER(LEN=26) :: progname
CHARACTER(LEN= 5) :: version
!DEC$ ATTRIBUTES REFERENCE :: logname, progname, version
END SUBROUTINE USELOG
END INTERFACE
The routine USELOG uses the following code for exporting:
!DEC$ ATTRIBUTES DLLEXPORT :: USELOG
!DEC$ ATTRIBUTES ALIAS:'USELOG' :: USELOG
!DEC$ ATTRIBUTES REFERENCE :: logname_, progname_, version_
When I view the dll using dependency walker the routine is shown as USELOG without any decoration.
Could someone please tell me how to import this correctly.
Regards, Mike
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You need to link against the .lib generated when the DLL was built. If you tried linking to the DLL directly, that was ignored.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I did link against the import lib. I have it listed in the Linker/Advanced/Import Lib.
I also added the import lib to the project.
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ah - I've seen that error before. That's not the right place to add that. You want it under Additional Dependencies. What you did was tell the linker to name the import library it creates, if it created one, which it won't for an executable project. Treat the import library the same as a static library.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are correct Steve. I think I moved the import lib address from the Additional Dependencies in an attempt to fix the original problem which is an unresolved external.
I am trying to use the routine USELOG from the dll. If I use an interface block in the calling program, I get this error:
error LNK2019: unresolved external symbol __imp__USELOG referenced in function _MAIN__ Besthb.obj
If I do not use an interface block, I get the following error:
error LNK2019: unresolved external symbol _USELOG referenced in function _MAIN__
Both errors say that the linker is looking for the routine USELOG with a prefix to the routine name.
Dependency Walker does not show any prefix when looking at the dll.
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I decided to try a different approach. I created a static library to replace the dll. I added that as the additional dependency instead of the dll import library. I eliminated the Interface block. However, I still get the error:
error LNK2019: unresolved external symbol _USELOG referenced in function _MAIN__
The USELOG routine does show up as _USELOG in a Dumpbin listing of the static library.
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I solved the underlying problem.
In the UseLog routine being exported from the dll, the DECORATE command was missing.
The codes should have read:
!DEC$ ATTRIBUTES DLLEXPORT :: USELOG
!DEC$ ATTRIBUTES DECORATE, ALIAS:'USELOG' :: USELOG
!DEC$ ATTRIBUTES REFERENCE :: logname_, progname_, version_
Question: Is it possible to tell the calling routine not to expect decoration?
Regards, Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You could remove the ALIAS,DECORATE directive entirely in both the called routine and the caller. since all you're doing is restating the default.
When you use DLLIMPORT, the __imp__prefix is added. This is resolved by the import library and tells the linker to optimize the call (removes a few extra instructions. You don't see the prefix when examining the library or DLL. DLLIMPORT is optional when calling procedures, but is required if you are referencing variables or COMMON blocks in DLLs.
I will also comment that a nice way to handle this sort of thing is to put your DLL routine in a module, with DLLEXPORT. Then when the called program USEs the module, it will automatically get the interface AND do a DLLIMPORT. DO make sure that the executable links to the DLL run-time libraries.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I use modules in VB, but haven't used them in Fortran.
Are you suggesting placing the entire routine in a module like the sample code below, or only a interface block?
MODULE MOD_TEST
SUBROUTINE UseLog(logname, progname, version)
!DEC$ ATTRIBUTES DLLEXPORT :: USELOG
!DEC$ ATTRIBUTES REFERENCE :: logname, progname, version
IMPLICIT NONE
INTERFACE
SUBROUTINE USE_LOG(logname, progname, version);
!DEC$ ATTRIBUTES DLLIMPORT :: USE_LOG
!DEC$ ATTRIBUTES DECORATE, ALIAS:'use_log' :: USE_LOG
CHARACTER(LEN=26) :: logname
CHARACTER(LEN=26) :: progname
CHARACTER(LEN=5) :: version
!DEC$ ATTRIBUTES REFERENCE :: logname, progname, version
END SUBROUTINE USE_LOG
END INTERFACE
! Type call list variables
CHARACTER(LEN=26), INTENT(IN) :: logname
CHARACTER(LEN=26), INTENT(IN) :: progname
CHARACTER(LEN=5), INTENT(IN) :: version
CALL Use_Log(logname, progname, version)
RETURN
END SUBROUTINE UseLog
END MODULE_TEST
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You would take out the INTERFACE - a routine in a module provides its own interface. See Doctor Fortran Gets Explicit - Again! for more information. Then add a USE MOD_TEST to the main program where you want the subroutine to be visible. You'll need to make the .mod file created when the module was compiled visible to the "Includes" path when building the executable. If you simply make the DLL project a dependent of the executable project, everything will be done automatically.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the sample code, the INTERFACE is actually for the routine USE_LOG which is a C routine in another dll. The Fortran routine USELOG is calling USE_LOG.
Mike
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ah, I see. Yes, you need an interface for the C routine.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page