Coding Requirements for Sharing Data in DLLs

A dynamic-link library (DLL) is an executable file that can be used as a place to share data across processes.

Coding requirements include using the cDEC$ ATTRIBUTES DLLIMPORT and DLLEXPORT compiler directives. Variables and routines declared in the program and in the DLL are not visible to each another unless you use DLLIMPORT and DLLEXPORT.

When sharing data among multiple threads or processes, do the following:

This section discusses:

Exporting and Importing Common Block Data

Data and code in a dynamic-link library is loaded into the same address space as the data and code of the program that calls it. However, variables and routines declared in the program and in the DLL are not visible to one another unless you use the cDEC$ ATTRIBUTES DLLIMPORT and DLLEXPORT compiler directives. These directives enable the compiler and linker to map to the correct portions of the address space so that the data and routines can be shared, allowing use of common block data across multiple images.

You can use DLLEXPORT to declare that a common block in a DLL is being exported to a program or another DLL. Similarly, you can use DLLIMPORT within a calling routine to tell the compiler that a common block is being imported from the DLL that defines it.

To export and import common block data:

  1. Create a common block in the subprogram that will be built into a Fortran DLL. Export that common block with a cDEC$ ATTRIBUTES DLLEXPORT directive, followed by the COMMON statement, associated data declarations, and any procedure declarations to be exported. For example:
     !DEC$ ATTRIBUTES DLLEXPORT :: /X/
         COMMON /X/ C, B, A
         REAL C, B, A
         END
         ...
    

    If the Fortran DLL procedure contains only a common block declaration, you can use the BLOCK DATA statement:

         BLOCK DATA T
     !DEC$ ATTRIBUTES DLLEXPORT :: /X/
         COMMON /X/ C, B, A
         REAL C, B, A
         END
    

    The Fortran procedure to be linked into a DLL can contain a procedure, such as the following:

        SUBROUTINE SETA(I)
     !DEC$ ATTRIBUTES DLLEXPORT :: SETA, /X/
          COMMON /X/ C, B, A
          REAL C, B, A
          INTEGER I
          A = A + 1.
          I = I + 1
          WRITE (6,*) 'In SETA subroutine, values of A and I:' , A, I
          RETURN
        END SUBROUTINE
    
  2. Refer to the common block in the main image with a cDEC$ ATTRIBUTES DLLIMPORT directive, followed by the local data declarations and any procedure declarations defined in the exported DLL. For example:
        PROGRAM COMMONX
     !DEC$ ATTRIBUTES DLLIMPORT:: SETA,  /X/
           COMMON /X/ C, B, A
           REAL C, B, A, Q
           EQUIVALENCE (A,Q)
    
         A = 0.
         I = 0
         WRITE (6,*) 'In Main program before calling SETA...'
         WRITE (6,*) 'values of A and I:' , A, I
    
         CALL SETA(I)
         WRITE (6,*) 'In Main program after calling SETA...'
         WRITE (6,*) 'values of A and I:' , Q, I
    
         A = A + 1.
         I = I + 1
         WRITE (6,*) 'In Main program after incrementing values'
      END PROGRAM COMMONX
    
  3. Build the DLL and then build the main program, as described in Building and Using Dynamic-Link Libraries.

Exporting and Importing Data Objects in Modules

You can give data objects in a module the DLLEXPORT property, in which case the object is exported from a DLL.

When a module is used in other program units, through the USE statement, any objects in the module with the DLLEXPORT property are treated in the program using the module as if they were declared with the DLLIMPORT property. So, a main program that uses a module contained in a DLL has the correct import attributes for all objects exported from the DLL.

You can also give some objects in a module the DLLIMPORT property. Only procedure declarations in INTERFACE blocks and objects declared EXTERNAL or with cDEC$ ATTRIBUTES EXTERN can have the DLLIMPORT property. In this case, the objects are imported by any program unit using the module.

If you use a module that is part of a DLL and you use an object from that module that does not have the DLLEXPORT or DLLIMPORT property, the results are undefined.

For more information: