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

Share COMMON BLOCK between EXE and 2 DLL's.

OpsEng
Beginner
1,034 Views

I have an old DLL (source code is lost) created with Compaq Visual Fortran that exports a common block.  I'm trying to add another DLL to the project that uses the same common block .  The main executable and DLL are developed with Intel Visual Fortran.  The program works fine if either one of the DLL's are added to the project, but fails with the IVF DLL (common block data not passed) if both DLL's are included.  Here are the code snippits:

      SUBROUTINE DLL1     ! Old DLL built with CVF or DVF
!DEC$ATTRIBUTES DLLEXPORT :: DLL1, NBR, TXT
      SUBROUTINE DLL2     ! New DLL built with IVF
!DEC$ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE :: DLL2
!DEC$ATTRIBUTES DECORATE, ALIAS:'DLL2' :: DLL2
!DEC$ATTRIBUTES DLLEXPORT :: /NBR/    ! Also tried DLLIMPORT linking against DLL1 .lib
!DEC$ATTRIBUTES DLLEXPORT :: /TXT/    ! Also tried DLLIMPORT linking against DLL1 .lib
      PROGRAM MAIN        ! Built with IVF
!DEC$ATTRIBUTES DLLIMPORT,STDCALL,REFERENCE,ALIAS:'_DLL1@0' :: DLL1
!DEC$ATTRIBUTES DLLIMPORT,STDCALL,REFERENCE,ALIAS:'_DLL2@0' :: DLL2
!DEC$ATTRIBUTES DLLIMPORT :: /NBR/
!DEC$ATTRIBUTES DLLIMPORT :: /TXT/
      CALL DLL1    ! Works OK
      CALL DLL2    ! Only works if DLL1 not imported


! The calling exe and both DLL's include the following:
      REAL*4       V1, V2
      COMMON/NBR/  V1(50),V2(75)
      CHARACTER*20 S1,S2
      COMMON/TXT/  S1,S2

Any suggestions or ideas what I'm doing wrong?

0 Kudos
5 Replies
Steven_L_Intel1
Employee
1,034 Views

You can't have two DLLs exporting the same symbol. When you want to share data, the data has to live in one DLL only where that item is exported. All other DLLs and EXEs link to that DLL (directly or indirectly) and import the symbol. You say you tried DLLIMPORT, but didn't say what the failure is.

0 Kudos
OpsEng
Beginner
1,034 Views

I've changed the DLL2 Common Block Attributes to DLLIMPORT and included the DLL1.lib file in the project.  When I debug, Visual Studio shows the common block data is passed ok while inside the DLL2 subroutine itself.  However when the DLL2 subroutine calls another subroutine inside the DLL2 DLL, the Common Block variables are all zero or blank.  The original Common Block data appears again when it steps back into the DLL2 subroutine.  Any changes that were made are lost.  Here are the new attributes used for the DLL2.DLL:

      SUBROUTINE DLL2     ! New DLL built with IVF
!DEC$ATTRIBUTES DLLEXPORT, STDCALL, REFERENCE :: DLL2
!DEC$ATTRIBUTES DECORATE, ALIAS:'DLL2' :: DLL2
!DEC$ATTRIBUTES DLLIMPORT :: /NBR/    
!DEC$ATTRIBUTES DLLIMPORT :: /TXT/  

Thanks you for your assistance.

0 Kudos
Steven_L_Intel1
Employee
1,034 Views

Can you attach a ZIP of a solution with the three projects so I can see what it looks like? I am always suspicious of snippets and paraphrases. I have done this type of sharing several times. Does this other subroutine in DLL2 also have the DLLIMPORT directives for the COMMONs? It needs to.

0 Kudos
OpsEng
Beginner
1,034 Views

After adding DLLIMPORT to the another subroutine in DLL2, everything works as expected.  I was under the assumption that the import attribute was only required at the entry subroutine for the DLL and that the common block would share nicely with the other subroutines in the DLL.

Attached are project files that duplicate the original issue (the code is just to duplicate the issue and has no functional value).

  CP - The calling program which calls DLL1 then DLL2.  DLL1 works ok using DLLEXPORT.   DLL2 returns with inputs unchanged.

  DLL1 - Uses DLLEXPORT for the Common Block.

  DLL2 - Uses DLLIMPORT for the Common Block.  When Subroutine CHANGE2 is called, the common block appears to go out of SCOPE unless a DLLIMPORT is also added to this subroutine. (the attached file does not include this second DLLIMPORT)

0 Kudos
Steven_L_Intel1
Employee
1,034 Views

The DLLIMPORT is needed in each routine as otherwise it doesn't know to look for the data export pointer. For procedures, DLLIMPORT is optional - an optimization - but for data it's required.

0 Kudos
Reply