Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29285 Discussions

Calling Fortran routine in mixed-language DLL from Fortran routine in mixed-language EXE

zalcjm
Beginner
471 Views

Using IVF 9.1 / Studio .NET 2003, I have been trying to build a Fortran/C mixed-language driver program EXE and a Fortran/C mixed-language DLL. When run from the command-line, the EXE is obviously supposed to call the DLL. The DLL contains mostly Fortran plus a few minor C source files that contain various routines. The build case was set up with the C being the main project (MAIN) and the Fortran components in a lib (MAIN_LIB). The Fortran source file containing the routine to be exported starts like:

subroutine ENITUOR(X,Y,Z)

!DEC$ ATTRIBUTES DLLEXPORT :: ENITUOR
!DEC$ ATTRIBUTES STDCALL,REFERENCE,ALIAS:"ENITUOR" :: ENITUOR

...

(Note: I have also tried eliminating the "STDCALL,REFERENCE" part without luck). The EXE workspace contains a C main project (the C really is the main program, in addition to being set up as the main project (DRIVER)) that calls a Fortran subroutine that resides in a library (DRIVER_LIB).The .lib output file from the DLL build is in the DRIVER solution; I have tried sticking it in the MAIN, MAIN_lib, or as a Solution Item. The DLL build seems to work ok, but the EXE build bombs with:

Main error LNK2019: unresolved external symbol _ENITUOR@112 referenced in function _SOME_NAME

So it boils down to this: How do I get a Fortran routine within a library in a C main project to call a Fortran routine within a mixed-language DLL built with the Fortran similarly being in a library? Could it be that the interfacefor the DLL import is not set up properly? It currently looks like:

INTERFACE
subroutine ENITUOR(X, Y, Z)
!DEC$ ATTRIBUTES DLLIMPORT :: ENITUOR
!DEC$ ATTRIBUTES REFERENCE, ALIAS:'ENITUOR':: ENITUOR
!DEC$ ATTRIBUTES REFERENCE :: X, Y, Z
type(SOMETYPE) :: X
integer(4) :: Y(1:20)
type(OTHERTYPE) :: Z
...

Thanks,

Jeff

0 Kudos
2 Replies
anthonyrichards
New Contributor III
471 Views
I think you need to examine the symbol table in your .LIB to see what symbol you are actually getting for subroutine ENITUOR (By the way, with 3 arguments, you would expect ENITUOR@12, so @112 is a misprint, no?). Then, when you have the symbol, put that into your ALIAS directive in the Fortran. Either that, or, if you have access to the code that generates the symbol, change it to ensure that ENTUOR is generated as the symbol, and not _ENTUOR or _ENTUOR@12 or some C-mangled horror.
0 Kudos
joerg_kuthe
Novice
471 Views

To my understanding, if you change the calling convention of a routine than you also have to comply to this when you call this routine.
You are changing the calling convention of your Fortran routine. For example:

subroutine ENITUOR(X,Y,Z)
!DEC$ ATTRIBUTES STDCALL, ALIAS:"enituor" :: ENITUOR
!DEC$ ATTRIBUTES DLLEXPORT :: ENITUOR
!DEC$ ATTRIBUTES REFERENCE :: X, Y, Z

thus you should call it the same way but no importing it (DLLIMPORT). This might be superfluous if the both the calling routine and the called routine are contained in the same DLL:

SUBROUTINE Caller(....)

INTERFACE
subroutine ENITUOR(X, Y, Z)
!DEC$ ATTRIBUTES STDCALL, ALIAS:"enituor" :: ENITUOR
!DEC$ ATTRIBUTES DLLIMPORT :: ENITUOR
!DEC$ ATTRIBUTES REFERENCE :: X, Y, Z
type(SOMETYPE) :: X
integer(4) :: Y(1:20)
type(OTHERTYPE) :: Z
END INTERFACE

CALL ENITUOR(X, Y, Z)

Hope this works.

Jrg Kuthe
www.qtsoftware.de

0 Kudos
Reply