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

DLLEXPORT and 16.x

Simon_Geard
New Contributor I
413 Views

Version 16.0.2.180

My solution has suddenly stopped honoring the dllexport directive. We have many functions of the form

      INTEGER *4 FUNCTION GETNTGRID()
!DEC$ ATTRIBUTES DLLEXPORT::GETNTGRID
          GETNTGRID = 3
      END FUNCTION GETNTGRID

The structure is to build a .lib file from the Fortran code then build a .dll from the .lib (and other C++ code). Procedures called with this structure are not a problem, the problem is with those procedures that are only used externally. I have used dumpbin to show that there are no external symbols in the .exp file corresponding to DLLEXPORT directives, the only symbols are those corresponding to entries in the .def file.

Is there a compiler switch that controls the interpretation of DLLEXPORT either directly or indirectly? With the same code base and Version 14.0.1.139 I do not get this behaviour (both with VS2010).

Thanks.

0 Kudos
5 Replies
Steven_L_Intel1
Employee
413 Views

No, there's no switch that controls this and I'm not aware of any changes. Can you provide a short but complete example that shows the problem? I took your snippet and it created a DLL with exported name normally.

0 Kudos
IanH
Honored Contributor II
413 Views

Generally there needs to be "something" to tell the linker that it needs to pull a chunk of object code out of a static library and link it into a DLL (or EXE).  This could be an explicit reference to the chunk of object code ultimately from an object file supplied in the linker command line, or an explicit mention of a symbol in the linker command line (/INCLUDE or /EXPORT) or the appearance of the symbol in a module definition file supplied to the linker.

The granularity of a stretch of object code generated by a compiler for a particular source file can vary - [very] historically one source file resulted in one monolithic chunk of object code that the linker then dealt with - if one thing in that chunk was referenced then the entire chunk was linked in.  However, compilers can package object code - perhaps putting each procedure in its own chunk - such that the linker can be quite selective about what it includes.  I'm not sure what ifort does in this regard, but this capability of the linker is controlled by the /OPT:REF or /OPT:NOREF options.

Perhaps the lack of (or change in) an explicit "something" to tell the linker that a particular stretch of object code from the library, perhaps combined with a relatively subtle change in how the compiler packages object code, now means that the linker is not including the object code from your static library that contains the procedures you intended to export.  If so, providing an explicit reference in the linker command line or module definition file is the simple fix.

0 Kudos
IanH
Honored Contributor II
413 Views

To supplement my blather - here are some tests (I don't have 14.0 installed to contrast and this is with the tools of VS2015).  Here's the file that will make up the pretend static library.

MODULE my_procedures
  IMPLICIT NONE
CONTAINS
  SUBROUTINE foo() BIND(C, NAME='foo')
  !DEC$ ATTRIBUTES DLLEXPORT :: foo
    PRINT *, 'my_procedures%%foo'
  END SUBROUTINE foo
  
  SUBROUTINE bar() BIND(C, NAME='bar')
  !DEC$ ATTRIBUTES DLLEXPORT :: bar
    PRINT *, 'my_procedures%%bar'
  END SUBROUTINE bar
END MODULE my_procedures

SUBROUTINE myexternal() BIND(C,NAME='myexternal')
  !DEC$ ATTRIBUTES DLLEXPORT :: myexternal
  PRINT *, 'myexternal'
END SUBROUTINE myexternal

Compile and archive that to a library, then link to a dll (dummy.f90 contains only a comment - so the compiler still bothers actually trying to compile and link).

>ifort /c /MD my_procedures.f90
Intel(R) Visual Fortran Compiler for applications running on IA-32, Version 16.0.2.180 Build 20160204
...
>lib my_procedures.obj
Microsoft (R) Library Manager Version 14.00.23506.0
...
>echo ! A comment to stop the compiler complaining > dummy.f90

>ifort /dll /MD dummy.f90 my_procedures.lib
...
>dumpbin /exports dummy.dll
Microsoft (R) COFF/PE Dumper Version 14.00.23506.0
...
Dump of file dummy.dll

File Type: DLL

  Summary

        2000 .data
        1000 .gfids
        6000 .rdata
        1000 .reloc
        A000 .text

...and there are no exported procedures.

But if we explicitly ask to include a symbol in the link (ditch the leading underscore on the symbol name for x64):

>ifort /dll /MD dummy.f90 my_procedures.lib /link /include:_foo
...
>dumpbin /exports dummy.dll
...
    ordinal hint RVA      name

          1    0 00001060 bar
          2    1 00001010 foo
          3    2 000010B0 myexternal

All three exported procedures from the static library are now in the DLL - and which also suggests that ifort generates object code that has a granularity of the entire source file.  Maybe that shoots my granularity theory down in flames, but regardless, I'd still recommend explicitly specifying what you want to go into the DLL.

0 Kudos
Steven_L_Intel1
Employee
413 Views

ATTRIBUTES DLLEXPORT turns into an "object directive". As soon as the linker pulls in the object file, no matter how many routines are in that object, all of the directives are processed. In Intel Fortran, you have to put the DLLEXPORT directive in the routine you want to export, otherwise it is ignored.

0 Kudos
Simon_Geard
New Contributor I
413 Views

I tried to find a simple way of reproducing this but failed. Using dumpbin, fgrep, sort and comm I was able to get a list of those symbols that have suddenly gone AWOL (about 270) but why it's started happening I've got no idea. If I can find a way or reproducing it I'll probably have to submit it to Premier Support since there are restrictions on what I can post to a public site. If I do ever find a solution I'll post it here.

0 Kudos
Reply