Using DLLs

The prelinker is used to build DLLs that export defined external functions and variables, and to build programs or DLLs that import external functions and variables from other DLLs.

Note: The prelinker NODYNAM option must not be in effect when using or building DLLs.

To assign a name to a DLL, use either the DLLNAME() prelinker option, or the NAME control statement. If you do not assign a name, and the data set SYSMOD is a PDS member, the member name is used as the DLL name. Otherwise, the name TEMPNAME is used.

To build a DLL, you need to compile object code that exports external functions or variables, then prelink and link that code into a load module. During the prelink step you need to capture the definition side-deck which is written to the ddname SYSDEFSD. The definition side-deck is a list of IMPORT control statements that correspond to the external functions and variables exported by the DLL.

Include the IMPORT statements at prelink time for any program that imports variables or functions from the DLL.

Example: In the following C example, EXPONLY is a DLL which only exports a single variable year:
/* EXPONLY.C */
int year = 2001;      /* exported from this DLL */
 
Example: In the following example, IMPEXP is a DLL that both imports and exports external functions and variables. It imports the external variable year from DLL EXPONLY, and exports external functions next_year and get_year.
/* IMPEXP.C */
extern int year;       /* imported from DLL EXPONLY */

void next_year(void) { /* exported from this DLL    */
  ++year;              /* load DLL EXPONLY, modify 'year' in DLL */
}

int get_year(void) {   /* exported from this DLL    */
  return year;         /* get value of 'year' from DLL EXPONLY */
}
 
Example: In the following example, IMPONLY is a program that only imports functions and variables. It imports the variable year from DLL EXPONLY, and it imports functions next_year and get_year from DLL IMPEXP.
/* IMPONLY.C */
#include <stdio.h>
extern int  get_year(void);    /* import from DLL IMPEXP */
extern void next_year(void);   /* import from DLL IMPEXP */
extern int year;               /* import from DLL EXPONLY */
int main(void)
{
  int y;
  next_year();         /* load DLL IMPEXP, call function from DLL */
  y = get_year();      /* call function in DLL IMPEXP */
  if (   y == 2002
      && year == 2002) /* get value of 'year' from DLL EXPONLY */
    printf("pass\n");
  else
    printf("fail\n");
  return 0;
}
 
Example: The following JCL builds the DLLs EXPONLY, IMPEXP, and the program IMPONLY, and then runs IMPONLY:
Figure 1. JCL to build DLLs
//* -------------------------------------------------------------
//CEXPONLY  EXEC EDCC,
//  INFILE='USERID.DLL.C(EXPONLY)',
//  OUTFILE='USERID.DLL.OBJECT(EXPONLY),DISP=SHR ',
//  CPARM='LONG RENT EXPORTALL'
//* -------------------------------------------------------------
//CIMPEXP   EXEC EDCC,
//  INFILE='USERID.DLL.C(IMPEXP)',
//  OUTFILE='USERID.DLL.OBJECT(IMPEXP),DISP=SHR ',
//  CPARM='LONG RENT DLL EXPORTALL'
//* -------------------------------------------------------------
//CIMPONLY  EXEC EDCC,
//  INFILE='USERID.DLL.C(IMPONLY)',
//  OUTFILE='USERID.DLL.OBJECT(IMPONLY),DISP=SHR ',
//  CPARM='LONG RENT DLL'
//* -------------------------------------------------------------
//LINK1     EXEC CBCL,PPARM='DLLNAME(EXPONLY)',
//  OUTFILE='USERID.DLL.LOAD(EXPONLY),DISP=SHR '
//PLKED.SYSIN    DD DSN=USERID.DLL.OBJECT(EXPONLY),DISP=SHR
//PLKED.SYSDEFSD DD DSN=USERID.DLL.IMPORTS(EXPONLY),DISP=SHR
//* -------------------------------------------------------------
//LINK2     EXEC CBCL,PPARM='DLLNAME(IMPEXP)',
//  OUTFILE='USERID.DLL.LOAD(IMPEXP),DISP=SHR '
//PLKED.SYSIN    DD DSN=USERID.DLL.OBJECT(IMPEXP),DISP=SHR
//               DD DSN=USERID.DLL.IMPORTS(EXPONLY),DISP=SHR
//PLKED.SYSDEFSD DD DSN=USERID.DLL.IMPORTS(IMPEXP),DISP=SHR
//* -------------------------------------------------------------
//LINK3     EXEC CBCL,
//  OUTFILE='USERID.DLL.LOAD(IMPONLY),DISP=SHR '
//PLKED.SYSIN    DD DSN=USERID.DLL.OBJECT(IMPONLY),DISP=SHR
//               DD DSN=USERID.DLL.IMPORTS(EXPONLY),DISP=SHR
//               DD DSN=USERID.DLL.IMPORTS(IMPEXP),DISP=SHR
//* -------------------------------------------------------------
//GO       EXEC PGM=IMPONLY
//STEPLIB  DD DSN=USERID.DLL.LOAD,DISP=SHR
//         DD DSN=CEE.SCEERUN,DISP=SHR
//         DD DSN=CEE.SCEERUN2,DISP=SHR
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
To see which functions and variables are imported or exported use the Prelinker Map. A portion of the Prelinker Map from step LINK2 is as follows:
========================================================================
|                           Load Module Map  1                         |
========================================================================

MODULE ID  MODULE NAME

  00001    EXPONLY


========================================================================
|                          Import Symbol Map  2                        |
========================================================================

*TYPE    FILE ID  MODULE ID  NAME

   D      00001     00001    year

*TYPE:  D=imported data  C=imported code


========================================================================
|                          Export Symbol Map  3                        |
========================================================================

*TYPE    FILE ID  NAME

   C      00001   get_year
   C      00001   next_year

*TYPE:  D=exported data  C=exported code
 1  Load Module Map
This section lists the load modules from which functions and variables are imported. The load module names come from the input IMPORT control statements processed.
 2  Import Symbol Map
This section lists the imported functions and variables. The MODULE ID indicates the DLL from which the function or variable is imported. The FILE ID indicates the file in which the IMPORT control statement was processed that resulted in this import.
 3  Export Symbol Map
This section lists the external functions and variables which are exported. For each symbol that is listed in this section, an IMPORT control statement is written out to the DDname SYSDEFSD, the definition side-deck.
Note: The export symbol map will not be produced when the NODYNAM option is in effect.