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

SUBMODULEs, DLLEXPORT and functions returning pointers to TYPEs

Deniz_S_
Beginner
1,041 Views

Reposting to the correct forum this time (fingers crossed).

I'm trying to split code into modules and submodules to minimize compile times. Anoher objective is to have two solutions, one with single project producing a console application, and another with multiple dll projects. I have built both solutions with IVF 16.2 under VS2010, however VS2010 integration is outdated for SUBMODULEs, functions drop down menu is blank, making it practically unworkable.

I decided to move on to to VS2017. I tried IVF 18.2 and IVF 17.7 that work with VS 2017, but there are issues:

1) Declaring functions that return pointers to types. If I declare the function in the module as: 

INTERFACE
...
MODULE FUNCTION getNextLink( this )
CLASS(link) :: this
CLASS(link), POINTER :: getNextLink
END FUNCTION getNextLink 
... 
END INTERFACE

and in the submodule as:

MODULE FUNCTION getNextLink( this )
IMPLICIT NONE
CLASS(link) :: this
CLASS(link), POINTER :: getNextLink
getNextLink => NULL()
IF(ASSOCIATED(this%NEXT)) getNextLink => this%NEXT
END FUNCTION getNextLink

IVF 16.2 compiles fine if getNextLink declaration in the submodule is commented.

IVF 18.2 compiles fine with declarations as above.

IVF 17.7 : Produces error #6227: This symbol has multiple POINTER statement/attribute declarations which is not allowed [GETNEXTLINK], with declarations as above. If getNextLink declaration in the submodule is commented, produces errors #6404: This name does not have a type, and must have an explicit type.   [GETNEXTLINK] and  #8227: The type of the target is not a dynamic type of the pointer.   [GETNEXTLINK]. I could not get 17.7 to work with any alternative, so leaving it aside.

2) DLLEXPORT declaration

With IVF16.2, with DLLEXPORT placed after function description in the SUBMODULE, and nothing in the MODULE, all worked fine

MODULE FUNCTION getNextLink( this ) !DEC$ ATTRIBUTES DLLEXPORT::getNextLink IMPLICIT NONE CLASS(link) :: this ...

With IVF 18.2, if I do as above, it complains with error #6122: The characteristics of the separate module procedure differ from those specified in the separate interface body

If I put the declaration in the module as well, it stops complaining and builds OK, but hits an exception at runtime, which I suspect is related. I checked with dumpbin /exports, and but seem to be exporting once only.

Where should the DLLEXPORT be placed in the split setup?

Thanks,

Deniz

0 Kudos
6 Replies
FortranFan
Honored Contributor III
1,041 Views

@Deniz,

Two quick suggestions if you can make use of them:

  1. Unfortunately the SUBMODULEs facility has seen several issues as well as regressions in Intel Fortran implementation.  As far as I can tell, the latest compiler update, Intel Fortran 19.0 Update 1, appears most reliable and which seems to include fixes for the issues you list above.  I suggest you try to upgrade to 19.0.1.
  2. Re: DLLEXPORT, for the sake of expediency and to punt on your question, I will suggest neither!  That is, if you can, try switching to module-definition (.DEF) files and not clutter the Fortran code with such OS and packaging-specific directives.
0 Kudos
Steve_Lionel
Honored Contributor III
1,041 Views

Note that .DEF files can't be used if you want to export or import variables. My own preference is to use DLLEXPORT, especially as if you put DLLEXPORT in a module, it automatically becomes DLLIMPORT when the module is USEd.

0 Kudos
FortranFan
Honored Contributor III
1,041 Views

I would strongly discourage the export or import of variables from DLLs notwithstanding any existing/legacy situations where one may not have a choice and be forced to work with global data in such a manner. 

Re: the method of exporting to use with DLLs, something which is specific to Windows OS, readers should rather read what is in Microsoft Docs: https://docs.microsoft.com/en-us/cpp/build/determining-which-exporting-method-to-use?view=vs-2017

0 Kudos
jimdempseyatthecove
Honored Contributor III
1,041 Views

FF, thanks for the link. I've added it to my favorites.

Jim Dempsey

0 Kudos
FortranFan
Honored Contributor III
1,041 Views

Steve Lionel (Ret.) wrote:

Note that .DEF files can't be used if you want to export or import variables. ..

This statement is incorrect: .DEF files can indeed be used to export and import variables and I show an example below.  It does involve a "mixed" approach in the sense that the consumer will need to use DLLIMPORT with the variables.  But note my earlier comment where I any way discourage the export and import variables from DLLs.  But if one still has to do so, there are bigger risks awaiting the folks in such a scenario than the one with the "mixed" approach.

So with that one in mind, say one has Fortran "library" code to be packages into a DLL like so:

module data_m
   integer, save :: n = 42
end module 
module procs_m
   use data_m, only : n
contains
   subroutine sub( x )
      integer, intent(inout) :: x
      x = n + 1
   end subroutine 
end module 

Then using Microsoft's documentation on EXPORTS, one can write a .DEF file as follows which makes use of DATA keyword:

LIBRARY Fdll
EXPORTS
     DATA_M_mp_N       DATA
     N = DATA_M_mp_N   DATA
     PROCS_M_mp_SUB    @1

Now a caller may have code as shown below where the "methods" exported from the DLL are "USEd from Fortran MODULE files thus gaining the benefits of explicit interfaces while the "data" exported from the DLL is imported using the DLLIMPORT compiler directive:

   use procs_m, only : sub
   !DIR$ ATTRIBUTES DLLIMPORT :: n
   integer :: x
   print *, "n = ", n
   call sub( x )
   print *, "x = ", x, "; expected is 43"
   print *, "Now set n to zero"
   n = 0
   call sub( x )
   print *, "x = ", x, "; expected is 1"
end

Users can compiler and link this in a reasonably straightforward manner in a Visual Studio project with suitable settings or from the command line:

C:\Temp>type Fdll.f90
module data_m
   integer, save :: n = 42
end module
module procs_m
   use data_m, only : n
contains
   subroutine sub( x )
      integer, intent(inout) :: x
      x = n + 1
   end subroutine
end module

C:\Temp>type Fdll.def
LIBRARY Fdll
EXPORTS
     DATA_M_mp_N       DATA
     N = DATA_M_mp_N   DATA
     PROCS_M_mp_SUB    @1

C:\Temp>ifort /c Fdll.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 19.0.0.117 Build 20180804
Copyright (C) 1985-2018 Intel Corporation.  All rights reserved.


C:\Temp>link Fdll.obj /dll /def:Fdll.def /out:Fdll.dll
Microsoft (R) Incremental Linker Version 14.14.26433.0
Copyright (C) Microsoft Corporation.  All rights reserved.

   Creating library Fdll.lib and object Fdll.exp

C:\Temp>dumpbin /exports Fdll.lib
Microsoft (R) COFF/PE Dumper Version 14.14.26433.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file Fdll.lib

File Type: LIBRARY

     Exports

       ordinal    name

                  DATA_M_mp_N
                  N
             1    PROCS_M_mp_SUB

  Summary

          BA .debug$S
          14 .idata$2
          14 .idata$3
           8 .idata$4
           8 .idata$5
           A .idata$6

C:\Temp>type p.f90
   use procs_m, only : sub
   !DIR$ ATTRIBUTES DLLIMPORT :: n
   integer :: x
   print *, "n = ", n
   call sub( x )
   print *, "x = ", x, "; expected is 43"
   print *, "Now set n to zero"
   n = 0
   call sub( x )
   print *, "x = ", x, "; expected is 1"
end

C:\Temp>ifort /c p.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 19.0.0.117 Build 20180804
Copyright (C) 1985-2018 Intel Corporation.  All rights reserved.


C:\Temp>link p.obj Fdll.lib /subsystem:console /out:p.exe
Microsoft (R) Incremental Linker Version 14.14.26433.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>p.exe
 n =           42
 x =           43 ; expected is 43
 Now set n to zero
 x =            1 ; expected is 1

C:\Temp>

 

0 Kudos
Steve_Lionel
Honored Contributor III
1,041 Views

You say it's incorrect and then say the consumer has to use DLLIMPORT. Which is it? (The latter.) I don't see an advantage to using .DEF files, especially when one needs to determine how names are decorated.

0 Kudos
Reply